CH#56C 异象石

一道贼可怕的题目,这能想到就想到,不能想到就等着被算法题目(日常)揍吧。
另外这道题有参考别人代码之嫌,实属弟弟行为,下次一定不。
题目链接:良心网站acwing
题意:中文题啊=_=
思路:LCA+set维护,首先你得要理解时间戳的概念,对于出现的异象石你可以发现一个规律叫做按照时间戳排序,异象石的节点连成一个圈,并且累加相邻的节点,最后得到的结果恰好是路径和的两倍,这是本题最为可怕的地方,因为你根本想不到竟然还可以这样累加,我下次该怎么想这种题目?手画样例?还是默默的把这种结论记下来?很难考到这么奇怪的题目吧,叹息。另外本题有个地方你记下时间戳以后,对应的pos位置也要记录下来。这就完成了。

#define _CRT_SECURE_NO_WARNINGS 1
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<queue>
#define ls rt<<1
#define rs rt<<1|1
#define pb push_back
#define fi first
#define se second
#define yes puts("YES")
#define no puts("NO")
#define ios ios::sync_with_stdio(0);
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define aint(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
using namespace std;
typedef long long LL;
typedef set<int>::iterator IT;
typedef pair<int, int> PII;
typedef vector<int> VI;
const int N = 1e5+9 ,M = 1e6+1;
const int Maxn=1000010;
const LL inf = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
LL qp(LL x,LL y){LL ans=1;x%=mod;while(y){if(y&1)ans=ans*x%mod;x=x*x%mod;y>>=1;}return ans;}
LL inv(LL x){return qp(x,mod-2);}
///head
int n ,m ;
int head[N], edge[N<<1], Next[N<<1], ver[N<<1], tot;
int pos[N], dfn[N] ,vis[N];
int dep[N], fa[N][20];
LL dis[N][20] ,ans;
set<int>s;
void add(int x, int y , int z){
    ver[++tot] = y , edge[tot] = z , Next[tot] = head[x] , head[x] = tot;
}
int cnt ;
void bfs(){
    queue<int>q;
    q.push(1); vis[1] = 1; dep[1] = 1;
    while(q.size()){
        int x = q.front();q.pop();
        for(int i = head[x]; i ; i = Next[i]){
            int y = ver[i];
            if(vis[y])continue;
            vis[y] = 1;
            dep[y] = dep[x] + 1;
            fa[y][0] = x;
            dis[y][0] = edge[i];
            for(int j = 1 ; j < 20 ;j ++){
                fa[y][j] = fa[fa[y][j-1]][j-1];
                dis[y][j] = dis[fa[y][j-1]][j-1] + dis[y][j-1];
            }
            q.push(y);
        }
    }
}

LL lca(int x,int y){
    LL res = 0;
    if(dep[x] > dep[y])swap(x , y);
    for(int i = 19; i >= 0; i --)
        if(dep[fa[y][i]] >= dep[x])res += dis[y][i],y = fa[y][i];
    if(x == y) return res;
    for(int i = 19 ; i >= 0; i --)
    if(fa[x][i] != fa[y][i])
        res += dis[x][i] + dis[y][i] , x = fa[x][i], y = fa[y][i];
    return res + dis[x][0] + dis[y][0];
}

void dfs(int x,int fa = -1){
    dfn[x] = ++cnt, pos[cnt] = x;
    for(int i = head[x]; i ; i = Next[i]){
        int y = ver[i];
        if(y == fa) continue;
        dfs(y ,x);
    }
}
IT L(IT it)
{
	if(it==s.begin())return --s.end();
	return --it;
}
IT R(IT it)
{
	if(it==--s.end())return s.begin();
	return ++it;
}

int main(){
    while(~scanf("%d", &n )){
        memset(head, 0 , sizeof head);
        s.clear(); ans = 0;
        for(int i = 1; i < n ; i ++){
            int x, y , z;
            scanf("%d %d %d" ,&x, &y , &z);
            add(x,y,z);
            add(y,x,z);
        }
        dfs(1);
        bfs();
        scanf("%d" , &m);
        while(m --){
            char op[4] ;
            int ope ;
            scanf("%s",op);
            if(op[0] == '+'){
                scanf("%d" , &ope);
                if(SZ(s)){
                    auto it1 = s.lower_bound(dfn[ope]);
                    if(it1 == s.end()) it1 = s.begin();
                    auto it2 = L(it1);
                    ans += lca(ope, pos[*it2]) + lca(ope,pos[*it1]) - lca(pos[*it1],pos[*it2]);
                }
                s.insert(dfn[ope]);
            }
            else if(op[0] == '-'){
                scanf("%d" , &ope);
                auto it1 = s.find(dfn[ope]);
                auto it2 = L(it1);
                it1 = R(it1);
                ans -= lca(ope , pos[*it2]) + lca(ope, pos[*it1]) - lca(pos[*it2] , pos[*it1]);
                s.erase(dfn[ope]);
            }
            else{
                printf("%lld\n",ans / 2);
            }
        }
    }
}
全部评论

相关推荐

点赞 评论 收藏
转发
点赞 收藏 评论
分享
正在热议
# 牛客帮帮团来啦!有问必答 #
1151686次浏览 17149人参与
# 通信和硬件还有转码的必要吗 #
11203次浏览 101人参与
# OPPO开奖 #
19203次浏览 267人参与
# 和牛牛一起刷题打卡 #
18982次浏览 1635人参与
# 实习与准备秋招该如何平衡 #
203393次浏览 3627人参与
# 大厂无回复,继续等待还是奔赴小厂 #
4972次浏览 30人参与
# 不去互联网可以去金融科技 #
20398次浏览 256人参与
# 通信硬件薪资爆料 #
265924次浏览 2484人参与
# 国企是理工四大天坑的最好选择吗 #
2227次浏览 34人参与
# 互联网公司评价 #
97692次浏览 1280人参与
# 简历无回复,你会继续海投还是优化再投? #
25037次浏览 354人参与
# 0offer是寒冬太冷还是我太菜 #
454871次浏览 5124人参与
# 国企和大厂硬件兄弟怎么选? #
53903次浏览 1012人参与
# 参加过提前批的机械人,你们还参加秋招么 #
14645次浏览 349人参与
# 硬件人的简历怎么写 #
82286次浏览 852人参与
# 面试被问第一学历差时该怎么回答 #
19398次浏览 213人参与
# 你见过最离谱的招聘要求是什么? #
28103次浏览 248人参与
# 学历对求职的影响 #
161242次浏览 1804人参与
# 你收到了团子的OC了吗 #
538745次浏览 6387人参与
# 你已经投递多少份简历了 #
344237次浏览 4963人参与
# 实习生应该准时下班吗 #
96978次浏览 722人参与
# 听劝,我这个简历该怎么改? #
63525次浏览 622人参与
牛客网
牛客企业服务