很模板的树链剖分题
注意什么时候用线段树上的标号,什么时候用点的标号。
#pragma comment(linker, "/STACK:102400000,102400000") #include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; const int maxn = 50005; int val_pre[maxn],val[maxn],siz[maxn],son[maxn],id[maxn],fa[maxn],top[maxn],dep[maxn]; int topw; int M,N,P; vector<int> G[maxn]; void dfs_1(int u,int f,int d) { siz[u] = 1; fa[u] = f; dep[u] = d; son[u] = 0; for(int i=0;i<G[u].size();i++) { int v = G[u][i]; if(v == f) continue; dfs_1(v,u,d+1); siz[u] += siz[v]; if(siz[son[u]] < siz[v]) son[u] = v; } } void dfs_2(int u,int tp) { top[u] = tp; id[u] = ++topw; if(son[u]) dfs_2(son[u],tp); for(int i=0;i<G[u].size();i++) { int v = G[u][i]; if(v == fa[u]|| v==son[u]) continue; dfs_2(v,v); } } void debug() { for(int i=1;i<=N;i++) { printf("%d siz:%d son:%d dep:%d fa:%d ",i,siz[i],son[i],dep[i],fa[i]); printf("top:%d id:%d\n",top[i],id[i]); } } //////////////////////////////////////// //Segment Tree #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int add[maxn<<2]; void push_down(int rt) { if(add[rt]) { add[rt<<1] += add[rt]; add[rt<<1|1] += add[rt]; add[rt] = 0; } } void build(int l,int r,int rt) { add[rt] = 0; if(l == r) { add[rt] = val[r]; return ; } int m = (l+r)>>1; build(lson); build(rson); } void update(int L,int R,int c,int l,int r,int rt) { if(L<=l && R>= r) { add[rt] += c; return ; } push_down(rt); int m = (l+r)>>1; if(L<=m) update(L,R,c,lson); if(R> m) update(L,R,c,rson); } int query(int x,int l,int r,int rt) { if(l == r) { return add[rt]; } push_down(rt); int m = (l+r)>>1; if(x <= m) query(x,lson); else query(x,rson); } void change(int u,int v,int add) { int fu = top[u],fv = top[v]; while(fu != fv) { //printf("fu:%d u:%d v:%d fv:%d \n",fu,u,v,fv); if(dep[fu] < dep[fv]) { swap(u,v);swap(fu,fv); } update(id[fu],id[u],add,1,topw,1); u = fa[fu]; fu = top[u]; } if(u == v) { update(id[u],id[v],add,1,topw,1); return; } else{ if(dep[u] > dep[v]) swap(u,v); update(id[u],id[v],add,1,topw,1); return ; } } int main() { //freopen("input.in","r",stdin); while(~scanf("%d%d%d",&N,&M,&P)) { for(int i=1;i<=N;i++) scanf("%d",&val_pre[i]); for(int i=1,a,b;i<=M;i++) { scanf("%d%d",&a,&b); G[a].push_back(b); G[b].push_back(a); } topw = 0; dfs_1(1,0,1); dfs_2(1,1); for(int i=1;i<=N;i++) { val[id[i]] = val_pre[i]; } build(1,topw,1); //debug(); char op[10]; int a,b,c; for(int i=0;i<P;i++) { scanf("%s",op); if(op[0] == ‘I‘) { scanf("%d%d%d",&a,&b,&c); change(a,b,c); } else if(op[0] == ‘D‘) { scanf("%d%d%d",&a,&b,&c); change(a,b,-c); } else if(op[0] == ‘Q‘) { scanf("%d",&a); int ans = query(id[a],1,topw,1); printf("%d\n",ans); } } for(int i=0;i<maxn;i++) G[i].clear(); } }
HDU3966-Aragorn's Story-树链剖分-点权
时间: 2024-11-15 19:21:45