POJ2763

来源:互联网 发布:qt5串口编程详解 编辑:程序博客网 时间:2024/06/08 19:41
/*题意:有一颗树,每条边有边权有两个操作:1、给出一个点x,求当前点s和点x所在的路径上的边的边权之和(然后s=x)。2、给出一个边i和一个值val,把第i条边的边权修改为val。节点数 1e5操作数1e5边权1e4val ≤ 1e4*/#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const int INF = 0x3f3f3f3f;const int maxn = 100000+10;int N,Q,S;int edge_cnt,tot;int value[maxn],head[maxn];struct Path{int to,next;}edge[maxn<<1];void ADD(int u,int v){edge[edge_cnt].to = v;edge[edge_cnt].next = head[u];head[u] = edge_cnt++;}struct path{int x,y,val;void read(){scanf("%d %d %d",&x,&y,&val);}}PATH[maxn];int size[maxn],son[maxn],fa[maxn],deep[maxn];void dfs1(int now,int father,int Deep){size[now] = 1;fa[now] = father;deep[now] = Deep;son[now] = 0;for(int i = head[now]; ~i; i = edge[i].next){int v = edge[i].to;if(v != father){dfs1(v,now,Deep+1);size[now] += size[v];if(size[son[now]] < size[v])son[now] = v;}}}int id[maxn],top[maxn],Rank[maxn];void dfs2(int now,int Top){id[now] = ++tot;top[now] = Top;Rank[id[now]] = now;if(son[now])dfs2(son[now],Top);for(int i = head[now]; ~i; i = edge[i].next){int v = edge[i].to;if(v != fa[now] && v != son[now])dfs2(v,v);}}struct Info{int sum;int l,r;};struct SGT{Info tree[maxn<<2];void pushUp(int now){tree[now].sum = tree[now<<1].sum+tree[now<<1|1].sum;}void build(int now,int l,int r){tree[now].l = l;tree[now].r = r;if(l == r){tree[now].sum = value[Rank[l]];return;}int Mid = (l+r)>>1;build(now<<1,l,Mid);build(now<<1|1,Mid+1,r);pushUp(now);}void update(int now,int idx,int val){if(tree[now].l == tree[now].r){tree[now].sum = val;return;}int Mid = (tree[now].l+tree[now].r)>>1;if(idx <= Mid)update(now<<1,idx,val);elseupdate(now<<1|1,idx,val);pushUp(now);}int query(int now,int l,int r){if(l <= tree[now].l && tree[now].r <= r){return tree[now].sum;}int ans = 0;int Mid = (tree[now].l+tree[now].r)>>1;if(l <= Mid)ans += query(now<<1,l,r);if(Mid < r)ans += query(now<<1|1,l,r);return ans;}};SGT sgt;int work(int s,int e){int tps = top[s];int tpe = top[e];int ans = 0;while(tps != tpe){if(deep[tps]<deep[tpe]){swap(s,e);swap(tps,tpe);}ans += sgt.query(1,id[tps],id[s]);s = fa[tps];tps = top[s];}if(s == e)return ans;//如果在同一个点上没有时间耗费if(deep[s] > deep[e]){swap(s,e);}ans += sgt.query(1,id[son[s]],id[e]);return ans;}int main(){while(~scanf("%d %d %d",&N,&Q,&S)){memset(head,-1,sizeof(head));edge_cnt = tot = 0;for(int i = 1; i < N; i++){PATH[i].read();ADD(PATH[i].x,PATH[i].y);ADD(PATH[i].y,PATH[i].x);}dfs1(1,0,1);dfs2(1,1);value[1] = 0;//因为点没有点权,只有边有,要把边权转化成点权。//把每条边的边权赋给,在id小的那个节点。for(int i = 1; i < N; i++){if(deep[PATH[i].x] < deep[PATH[i].y])swap(PATH[i].x,PATH[i].y);value[PATH[i].x] = PATH[i].val;}sgt.build(1,1,N);int op,u,v;while(Q--){scanf("%d",&op);if(op){scanf("%d %d",&u,&v);sgt.update(1,id[PATH[u].x],v);}else{scanf("%d",&u);printf("%d\n",work(S,u));S = u;}}}return 0;}

原创粉丝点击