bzoj 3991 [SDOI2015]寻宝游戏

http://www.elijahqi.win/archives/3341
Description
小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达。游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路上行走,若走到某个村庄中有宝物,则视为找到该村庄内的宝物,直到找到所有宝物并返回到最初转移到的村庄为止。小B希望评测一下这个游戏的难度,因此他需要知道玩家找到所有宝物需要行走的最短路程。但是这个游戏中宝物经常变化,有时某个村庄中会突然出现宝物,有时某个村庄内的宝物会突然消失,因此小B需要不断地更新数据,但是小B太懒了,不愿意自己计算,因此他向你求助。为了简化问题,我们认为最开始时所有村庄内均没有宝物

Input
第一行,两个整数N、M,其中M为宝物的变动次数。

接下来的N-1行,每行三个整数x、y、z,表示村庄x、y之间有一条长度为z的道路。
接下来的M行,每行一个整数t,表示一个宝物变动的操作。若该操作前村庄t内没有宝物,则操作后村庄内有宝物;若该操作前村庄t内有宝物,则操作后村庄内没有宝物。

Output
M行,每行一个整数,其中第i行的整数表示第i次操作之后玩家找到所有宝物需要行走的最短路程。若只有一个村庄内有宝物,或者所有村庄内都没有宝物,则输出0。

Sample Input
4 5
1 2 30
2 3 50
2 4 60
2
3
4
2
1
Sample Output
0
100
220
220
280
HINT
1<=N<=100000

1<=M<=100000
对于全部的数据,1<=z<=10^9
Source
Round 1 感谢yts1999上传

结论题 考虑最短距离应该就是两两之间距离*2即可

那么用set模拟虚树建树的过程 每次在set里面动态维护dfs序列 的大小关系那么新插入就相当于找一个dfs序列上与我相邻的两个点 即前驱后继 那么计算答案的时候只需要 将 当前点到前驱后继的答案加上减去前去到后继的距离即可 删除同理 为逆操作

#include<set>
#include<cstdio>
#include<cctype>
#include<algorithm>
#define ll long long
using namespace std;
inline char gc(){
    static char now[1<<16],*S,*T;
    if(T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
    while(isdigit(ch)) x=x*10+ch-'0',ch=gc();
    return x*f;
}
const int N=100100;
const int inf=0x3f3f3f3f;
struct node{
    int y,next,z;
}data[N<<1];
int h[N],dep[N],dfn[N],n,m,Log[N],fa[N][20],cnt,num;ll dis[N],ans;bool mark[N];
struct cmp{
    inline bool operator()(const int &a,const int &b){return dfn[a]<dfn[b];}
};
set<int,cmp> s;
set<int,cmp>::iterator it1,it2;
inline void dfs(int x){
    dfn[x]=++cnt;
    for (int i=h[x];i;i=data[i].next){
        int y=data[i].y,z=data[i].z;if(y==fa[x][0]) continue;
        dep[y]=dep[x]+1;dis[y]=dis[x]+data[i].z;fa[y][0]=x;
        for (int j=1;j<=Log[dep[y]];++j) fa[y][j]=fa[fa[y][j-1]][j-1];dfs(y);
    }
}
inline int lca(int x,int y){
    if(dep[x]<dep[y]) swap(x,y);int dis=dep[x]-dep[y];
    for (int i=0;i<=Log[dis];++i) if ((1<<i)&dis) x=fa[x][i];
    if (x==y) return x;
    for (int i=Log[dep[y]];~i;--i) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}
inline ll calc(int x,int y){
    return dis[x]+dis[y]-(dis[lca(x,y)]<<1);
}
int main(){
    freopen("bzoj3991.in","r",stdin);
    n=read();m=read();Log[0]=-1;for (int i=1;i<=n;++i) Log[i]=Log[i>>1]+1;
    for (int i=1;i<n;++i){
        int x=read(),y=read(),z=read();
        data[++num].y=y;data[num].next=h[x];h[x]=num;data[num].z=z;
        data[++num].y=x;data[num].next=h[y];h[y]=num;data[num].z=z;
    }dfs(1);cnt=0;
    for (int i=1;i<=m;++i){
        int t=read();
        if (mark[t]){
            --cnt;mark[t]=0;if (cnt<=1) {s.erase(t);puts("0");continue;}
            it1=s.lower_bound(t);it2=s.upper_bound(t);
            if (it1==s.begin()){
                it1=s.end();--it1;
                ans-=calc(t,*it1);ans-=calc(t,*it2);ans+=calc(*it1,*it2);
                s.erase(t);printf("%lld\n",ans);continue;
            }
            if (it2==s.end()){
                --it1;it2=s.begin();
                ans-=calc(t,*it1);ans-=calc(t,*it2);ans+=calc(*it1,*it2);
                s.erase(t);printf("%lld\n",ans);continue;
            }--it1;s.erase(t);
            ans-=calc(t,*it1);ans-=calc(t,*it2);ans+=calc(*it1,*it2);
            printf("%lld\n",ans);
        }else{
            ++cnt;mark[t]=1;if (cnt<=1) {s.insert(t);puts("0");continue;}
            it1=s.lower_bound(t);it2=s.upper_bound(t);
            if (it1==s.begin()){
                it1=s.end();--it1;
                ans+=calc(t,*it1);ans+=calc(t,*it2);ans-=calc(*it1,*it2);
                s.insert(t);printf("%lld\n",ans);continue;
            }
            if (it2==s.end()){
                --it1;it2=s.begin();
                ans+=calc(t,*it1);ans+=calc(t,*it2);ans-=calc(*it1,*it2);
                s.insert(t);printf("%lld\n",ans);continue;
            }--it1;s.insert(t);
            ans+=calc(t,*it1);ans+=calc(t,*it2);ans-=calc(*it1,*it2);
            printf("%lld\n",ans);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/elijahqi/article/details/80261763