题意: 树上路径之间的点统一加减k,查询某点的值
解法:不会LCA的解法,于是用树链剖分了,比较简单的剖分,然后用线段树维护就行了,相当于区间更新,单点查询,查询点 i 的值时,只需在线段树中查询pos[u]位置的值即可。
加IO优化900+ms
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> using namespace std; #define N 50007 int siz[N]; //子树大小 int son[N]; //重儿子 int dep[N]; //深度 int pos[N]; //在线段树中的位置 int Top[N]; //所在重链的祖先 int fa[N]; //父节点 int head[2*N],tot,POS,n,m,q; struct Edge { int v,next; }G[2*N]; int tree[4*N],mark[4*N],a[N]; void init() { POS = tot = 0; memset(head,-1,sizeof(head)); memset(son,-1,sizeof(son)); memset(tree,0,sizeof(tree)); memset(mark,0,sizeof(mark)); } void addedge(int u,int v) { G[tot].v = v, G[tot].next = head[u], head[u] = tot++; G[tot].v = u, G[tot].next = head[v], head[v] = tot++; } void pushdown(int l,int r,int rt) { int mid = (l+r)/2; if(mark[rt]) { mark[2*rt] += mark[rt]; mark[2*rt+1] += mark[rt]; tree[2*rt] += mark[rt]*(mid-l+1); tree[2*rt+1] += mark[rt]*(r-mid); mark[rt] = 0; } } void update(int l,int r,int aa,int bb,int k,int rt) { if(aa <= l && bb >= r) { tree[rt] += k*(r-l+1); mark[rt] += k; return; } int mid = (l+r)/2; if(aa <= mid) update(l,mid,aa,bb,k,2*rt); if(bb > mid) update(mid+1,r,aa,bb,k,2*rt+1); } int query(int l,int r,int pos,int rt) { if(l == r) return tree[rt]; pushdown(l,r,rt); int mid = (l+r)/2; if(pos <= mid) return query(l,mid,pos,2*rt); else return query(mid+1,r,pos,2*rt+1); } void dfs(int u,int f) { dep[u] = dep[f]+1; siz[u] = 1; for(int i=head[u];i!=-1;i=G[i].next) { int v = G[i].v; if(v == f) continue; fa[v] = u; dfs(v,u); if(son[u] == -1 || siz[v] > siz[son[u]]) son[u] = v; siz[u] += siz[v]; } } void dfs2(int u,int father) { pos[u] = ++POS; Top[u] = father; if(son[u] != -1) dfs2(son[u],father); for(int i=head[u];i!=-1;i=G[i].next) { int v = G[i].v; if(v != fa[u] && v != son[u]) dfs2(v,v); } } void Change(int u,int v,int k) { int fx = Top[u], fy = Top[v]; while(fx != fy) { if(dep[fx] < dep[fy]) { swap(u,v); swap(fx,fy); } update(1,POS,pos[fx],pos[u],k,1); u = fa[fx]; fx = Top[u]; } if(dep[u] > dep[v]) swap(u,v); update(1,POS,pos[u],pos[v],k,1); } inline int in() { char ch; int a = 0; while((ch = getchar()) == ' ' || ch == '\n'); a += ch - '0'; while((ch = getchar()) != ' ' && ch != '\n') { a *= 10; a += ch - '0'; } return a; } int main() { int u,v,k,i; char ss[5]; while(scanf("%d%d%d",&n,&m,&q)!=EOF) { init(); for(i=1;i<=n;i++) a[i] = in(); for(i=1;i<n;i++) { u = in(), v = in(); addedge(u,v); } dep[0] = 0; dfs(1,0); dfs2(1,1); for(i=1;i<=n;i++) update(1,POS,pos[i],pos[i],a[i],1); while(q--) { scanf("%s",ss); if(ss[0] == 'Q') { u = in(); printf("%d\n",query(1,POS,pos[u],1)); } else { u = in(), v = in(), k = in(); if(ss[0] == 'I') Change(u,v,k); else Change(u,v,-k); } } } return 0; }