【SDOI2015】【BZOJ3991】寻宝游戏
2016-01-25 17:25
357 查看
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上传
感人至深..如今我终于会了这个当时被我看成裸链剖还没A的题了
其实是虚树
动态维护关键点的虚树
Set维护一下DFS序,答案就是相邻两点之和加上首末两点距离减去所有关键点的LCA
小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上传
感人至深..如今我终于会了这个当时被我看成裸链剖还没A的题了
其实是虚树
动态维护关键点的虚树
Set维护一下DFS序,答案就是相邻两点之和加上首末两点距离减去所有关键点的LCA
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<set> #define MAXN 100010 #define MAXINT 0x7fffffff #define GET (ch>='0'&&ch<='9') #define LL long long using namespace std; set<int> S; int n,m,top,Top; int fa[MAXN][17],id[MAXN],dfn[MAXN],deep[MAXN]; LL dis[MAXN],ans,delta; bool on[MAXN]; inline void in(int &x) { char ch=getchar();x=0; while (!GET) ch=getchar(); while (GET) x=x*10+ch-'0',ch=getchar(); } struct edge { int to,w; edge *next; }e[MAXN<<1],*prev[MAXN]; inline void insert(int u,int v,int w) { e[++top].to=v;e[top].next=prev[u];prev[u]=&e[top];e[top].w=w; } inline void dfs(int x,int f) { dfn[x]=++Top;id[dfn[x]]=x;fa[x][0]=f; for (int i=1;(1<<i)<=deep[x];i++) fa[x][i]=fa[fa[x][i-1]][i-1]; for (edge *i=prev[x];i;i=i->next) if (i->to!=f) deep[i->to]=deep[x]+1,dis[i->to]=dis[x]+i->w,dfs(i->to,x); } inline int lca(int x,int y) { if (deep[x]<deep[y]) swap(x,y); int t=deep[x]-deep[y]; for (int i=0;i<=16;i++) if ((1<<i)&t) x=fa[x][i]; for (int i=16;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return x==y?x:fa[x][0]; } inline LL Dis(int x,int y) { int LCA=lca(x,y); return dis[x]+dis[y]-2*dis[LCA]; } int main() { in(n);in(m);int u,v,w; for (int i=1;i<n;i++) in(u),in(v),in(w),insert(u,v,w),insert(v,u,w); dfs(1,0);S.insert(MAXINT);S.insert(-MAXINT); for (int i=1;i<=m;i++) { in(u);int flag=1;delta=0; if (on[u]) S.erase(dfn[u]),flag=-1; else S.insert(dfn[u]); on[u]^=1; int l=*--S.lower_bound(dfn[u]),r=*S.upper_bound(dfn[u]); if (r<MAXINT) ans+=flag*Dis(id[r],u); if (l>-MAXINT) ans+=flag*Dis(id[l],u); if (r<MAXINT&&l>-MAXINT) ans-=flag*Dis(id[l],id[r]); if (S.size()>2) l=*S.upper_bound(-MAXINT),r=*--S.lower_bound(MAXINT),delta=Dis(id[l],id[r]); printf("%lld\n",ans+delta); } }
相关文章推荐
- bzoj2780 广义后缀自动机+parent树+Dfs序+树状数组
- BZOJ2434 [Noi2011]阿狸的打字机【AC自动机+dfs序+树状数组】
- 树 (罗雨屏)
- Codevs 2370 小机房的树 LCA 树上倍增
- 树 (罗雨屏)倍增+dfs
- SPOJ QTREE 1-3题解
- bzoj-2780 Sevenk Love Oimaster
- bzoj-2051 A Problem For Fun
- 【基础练习】【倍增LCA】codevs1036 商务旅行题解
- 【基础练习】【倍增LCA】codevs1503 愚蠢的宠物
- HDU 5468 Puzzled Elena (2015年上海赛区网络赛A题)
- 【BZOJ3252】攻略
- codeforces #316 D.Tree Requests (巧妙的dfs序)
- HDU 5274(LCA + 线段树)
- HDU 3794 Assign the task (时间戳dfs序线段树)
- Codeforces Round #316 (Div. 2) D. Tree Requests
- Codevs P1036 商务旅行
- bzoj 2783 [JLOI2012] 树 题解
- CF 题目集锦 PART 5 #266 div 2 E
- 【LCA】最近公共祖先问题Lowest Common Ancestors