lca:异象石(set+dfs序)

题目:https://loj.ac/problem/10132

#include<bits/stdc++.h>
using namespace std;
int n,m,tot=0,N,k=0,head[5000000];
struct node{
    int to,next,w;
}e[5000000];
int depth[9000000],grand[2000000][20],c[5000000],num[5990000];
long long d[9000000];
void add(int x,int y,int c)
{
    e[++tot].next=head[x],e[tot].w=c,e[tot].to=y,head[x]=tot;
}
void init()
{
    N=floor(log(n+0.0)/log(2.0));
    depth[1]=1;
}
void dfs(int x)
{
    num[x]=++k;c[k]=x;
    for(int i=1;i<=N;i++)grand[x][i]=grand[grand[x][i-1]][i-1];
    for(int i=head[x];i;i=e[i].next)
    {
        int v=e[i].to;
        if(v==grand[x][0])continue;
        depth[v]=depth[x]+1;
        grand[v][0]=x;
        d[v]=d[x]+e[i].w;
        dfs(v);
    }
}
int lca(int a,int b)
{
    if(depth[a]>depth[b]) swap(a,b);
    for(int i=N;i>=0;i--){
        if(depth[a]<depth[b]&&depth[grand[b][i]]>=depth[a]) b=grand[b][i];
    }
    if(a==b) return a;
    for(int i=N;i>=0;i--){
        if(grand[a][i]!=grand[b][i]){a=grand[a][i],b=grand[b][i];}
    }
    return grand[a][0];
}
set<int> s;
#define Auto set<int>::iterator
Auto Left(Auto t)
{
    if(t==s.begin()) return --s.end();
    return --t;
}
Auto Right(Auto t)
{
    if(t==--s.end()) return s.begin();
    return ++t;
}
long long dist(int x,int y)
{
    return d[x]+d[y]-(d[lca(x,y)]<<1);
}
int main()
{
    char ch[10];
    scanf("%d",&n);
    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);
    }
    init();
    dfs(1);
    scanf("%d",&m);
    Auto l,r;
    long long ans=0;
    for(int i=1;i<=m;i++){
        scanf("%s",ch);
        if(ch[0]=='?') printf("%lld\n",ans>>1);
        else{
            int x;
            scanf("%d",&x);
            if(ch[0]=='+')
            {
                if(!s.empty())
                {
                    r=s.lower_bound(num[x]);
                    if(r==s.end())r=s.begin();
                    l=Left(r);
                    ans+=dist(c[*l],x)+dist(x,c[*r])-dist(c[*l],c[*r]);
                }
                s.insert(num[x]);
            }
            else{
                r=s.find(num[x]);
                l=Left(r);r=Right(r);
                ans-=dist(c[*l],x)+dist(x,c[*r])-dist(c[*l],c[*r]);
                s.erase(num[x]);
            }
        }
    } 
    return 0;
}

  

posted @ 2018-09-04 16:54  南柯一场  阅读(354)  评论(0编辑  收藏  举报