题意:给定一棵树,有3种操作,增加或减少两个点路径上所有点的值,查询某个点的值
思路:把树剖分成链,剩下的就是一个有laze标记的线段树,点权和边权不同的地方就在qurey函数中while()下面的几行
#include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; typedef long long ll; #define lson(x) 2*x #define rson(x) 2*x+1 const int maxn = 5e5+5; struct Edge { int to,next; }edge[maxn*2]; int head[maxn],tot,cnt; int root,size[maxn],dep[maxn],fa[maxn],son[maxn]; int top[maxn],id[maxn],val[maxn],a[maxn]; /* size -> 以x为根节点子树的大小 dep -> 深度 fa -> 父节点 son -> 重儿子 top -> x所在重链的顶端节点 id -> 这个点在线段树中的位置 */ struct data { int l,r,num,laz; }node[maxn*4]; void init() { memset(head,-1,sizeof head); tot = 0; cnt = 0; } void add(int x,int y) { edge[tot].to = y; edge[tot].next = head[x]; head[x] = tot++; } int dfs1(int x,int pre,int d) { size[x] = 1; fa[x] = pre; dep[x] = d; son[x] = 0; for(int i = head[x]; i != -1; i = edge[i].next) { int y = edge[i].to; if(y != pre) { size[x] += dfs1(y,x,d+1); if(size[y] > size[son[x]]) son[x] = y; } } return size[x]; } void dfs2(int x,int pre) { id[x] = ++cnt; top[x] = pre; if(son[x]) dfs2(son[x],pre); //重链 for(int i = head[x]; i != -1; i = edge[i].next) { int y = edge[i].to; if(y != fa[x] && y != son[x]) dfs2(y,y); //轻链 } } void pushup(int cnt) { node[cnt].num = node[lson(cnt)].num + node[rson(cnt)].num; } void build(int x,int y, int cnt) { node[cnt].l = x; node[cnt].r = y; node[cnt].laz = 0; if(x == y) { node[cnt].num = val[x]; return; } int mid = (x+y) / 2; build(x,mid,lson(cnt)); build(mid+1,y,rson(cnt)); pushup(cnt); } void down(int cnt) { if(node[cnt].laz == 0) return; int val = node[cnt].laz; node[lson(cnt)].laz += val; node[rson(cnt)].laz += val; node[lson(cnt)].num += val * (node[lson(cnt)].r - node[lson(cnt)].l + 1); node[rson(cnt)].num += val * (node[rson(cnt)].r - node[rson(cnt)].l + 1); node[cnt].laz = 0; } void up(int x,int y,int cnt,int val) { if(x == node[cnt].l && y == node[cnt].r) { node[cnt].laz += val; node[cnt].num += val * (node[cnt].r - node[cnt].l + 1); return; } down(cnt); int fa = 2*cnt; if(x <= node[fa].r) { if(y <= node[fa].r) up(x,y,fa,val); else up(x,node[fa].r,fa,val); } fa++; if(y >= node[fa].l) { if(x >= node[fa].l) up(x,y,fa,val); else up(node[fa].l,y,fa,val); } pushup(cnt); } int fid(int x,int y,int cnt) { down(cnt); int res = 0; if(x == node[cnt].l && y == node[cnt].r) { return node[cnt].num; } int fa = 2*cnt; if(x <= node[fa].r) { if(y <= node[fa].r) res += fid(x,y,fa); else res += fid(x,node[fa].r,fa); } fa++; if(y >= node[fa].l) { if(x >= node[fa].l) res += fid(x,y,fa); else res += fid(node[fa].l,y,fa); } return res; } void qurey(int u,int v,int val) { while(top[u] != top[v]) { if(dep[top[u]] < dep[top[v]]) swap(u,v); up(id[top[u]],id[u],1,val); u = top[u]; u = fa[u]; } if(dep[u] > dep[v]) swap(u,v); up(id[u],id[v],1,val); return; } int main() { int n,m,q; while(scanf("%d%d%d",&n,&m,&q)!=EOF) { init(); for(int i = 1; i <= n; i++) scanf("%d",&a[i]); for(int i = 1; i <= m; i++) { int a,b; scanf("%d%d",&a,&b); add(a,b); add(b,a); } root = (n+1) / 2; dfs1(root,root,1); dfs2(root,root); for(int i = 1; i <= n; i++) val[id[i]] = a[i]; build(1,cnt,1); while(q--) { char op[5]; int a,b,k; scanf("%s",op); if(op[0]=='I') { scanf("%d%d%d",&a,&b,&k); qurey(a,b,k); } else if(op[0]=='D') { scanf("%d%d%d",&a,&b,&k); qurey(a,b,-k); } else { scanf("%d",&k); printf("%d\n",fid(id[k],id[k],1)); } } } }