题目大意:给出一棵无根树。开始的时候你在1号节点。有两种操作:1.求你的位置到x的位置的距离,然后你走到x点。2.把第x条边边权改成y。
思路:裸地树链剖分。当然正解不是树链剖分,是DFS序+树状数组。没时间想太多就写了个链剖。
CODE:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 200010 #define LEFT (pos << 1) #define RIGHT (pos << 1|1) using namespace std; struct Edge{ int x,y,len; Edge(int _x,int _y,int _len) :x(_x),y(_y),len(_len) {} Edge() {} }edge[MAX]; int points,asks,now; int head[MAX],total; int next[MAX],aim[MAX],length[MAX]; int src[MAX]; int son[MAX],father[MAX],deep[MAX]; int top[MAX],pos[MAX],cnt; int tree[MAX << 2]; inline void Add(int x,int y,int len); int PreDFS(int x,int last); void DFS(int x,int last,int root); void BuildTree(int l,int r,int pos); inline int Ask(int x,int y); int Ask(int l,int r,int x,int y,int pos); void Modify(int l,int r,int x,int pos,int num); int main() { cin >> points >> asks >> now; for(int x,y,z,i = 1;i < points; ++i) { scanf("%d%d%d",&x,&y,&z); edge[i] = Edge(x,y,z); Add(x,y,z),Add(y,x,z); } PreDFS(1,0); DFS(1,0,1); for(int i = 1;i <= total; ++i) { int temp = deep[edge[i].x] > deep[edge[i].y] ? edge[i].x:edge[i].y; src[pos[temp]] = edge[i].len; } BuildTree(1,cnt,1); for(int flag,x,y,i = 1;i <= asks; ++i) { scanf("%d%d",&flag,&x); if(!flag) { printf("%d\n",Ask(now,x)); now = x; } else { scanf("%d",&y); int temp = deep[edge[x].x] > deep[edge[x].y] ? edge[x].x:edge[x].y; Modify(1,cnt,pos[temp],1,y); } } return 0; } inline void Add(int x,int y,int len) { next[++total] = head[x]; aim[total] = y; length[total] = len; head[x] = total; } int PreDFS(int x,int last) { deep[x] = deep[last] + 1; father[x] = last; int re = 1,_max = 0; for(int i = head[x];i;i = next[i]) { if(aim[i] == last) continue; int temp = PreDFS(aim[i],x); if(temp > _max) temp = _max,son[x] = aim[i]; re += temp; } return re; } void DFS(int x,int last,int root) { pos[x] = ++cnt; top[x] = root; if(son[x]) DFS(son[x],x,root); for(int i = head[x];i;i = next[i]) { if(aim[i] == last || aim[i] == son[x]) continue; DFS(aim[i],x,aim[i]); } } void BuildTree(int l,int r,int pos) { if(l == r) { tree[pos] = src[l]; return ; } int mid = (l + r) >> 1; BuildTree(l,mid,LEFT); BuildTree(mid + 1,r,RIGHT); tree[pos] = tree[LEFT] + tree[RIGHT]; } inline int Ask(int x,int y) { int re = 0; while(top[x] != top[y]) { if(deep[top[x]] < deep[top[y]]) swap(x,y); re += Ask(1,cnt,pos[top[x]],pos[x],1); x= father[top[x]]; } if(x == y) return re; if(deep[x] < deep[y]) swap(x,y); re += Ask(1,cnt,pos[y] + 1,pos[x],1); return re; } int Ask(int l,int r,int x,int y,int pos) { if(l == x && r == y) return tree[pos]; int mid = (l + r) >> 1; if(y <= mid) return Ask(l,mid,x,y,LEFT); if(x > mid) return Ask(mid + 1,r,x,y,RIGHT); int left = Ask(l,mid,x,mid,LEFT); int right = Ask(mid + 1,r,mid + 1,y,RIGHT); return left + right; } void Modify(int l,int r,int x,int pos,int num) { if(l == r) { tree[pos] = num; return ; } int mid = (l + r) >> 1; if(x <= mid) Modify(l,mid,x,LEFT,num); else Modify(mid + 1,r,x,RIGHT,num); tree[pos] = tree[LEFT] + tree[RIGHT]; }