[树链剖分]
来源:互联网 发布:linux系统编辑文件 编辑:程序博客网 时间:2024/06/05 05:29
/*HDU 3966题意:给n个结点,m条边,p次操作I x y kD x y kx->y的路径上的节点都增加或减少kQ x 查询x结点的权值*/#include <bits/stdc++.h>using namespace std;const int maxn = 50010;int val[maxn],cnt,head[maxn],n;int d[maxn],f[maxn],sz[maxn],son[maxn],top[maxn],id[maxn],tot,rk[maxn];int t[maxn<<2],a[maxn],add[maxn<<2];/*建图*/struct node{ int to,next;} e[maxn<<1];void Init(){ memset(head,-1,sizeof(head)); cnt=0; memset(son,-1,sizeof(son)); tot=0;}void addEdge(int u,int v){ e[cnt].to=v; e[cnt].next=head[u]; head[u]=cnt++;}/*树链剖分*/void dfs1(int u,int fa,int depth){ f[u]=fa; d[u]=depth; sz[u]=1; for(int i=head[u]; ~i; i=e[i].next) { int v=e[i].to; if(v!=f[u]) { dfs1(v,u,depth+1); sz[u]+=sz[v]; if(son[u]==-1||sz[son[u]]<sz[v]) son[u]=v; } }}void dfs2(int u,int tp)/*重新编号*/{ top[u]=tp; id[u]=++tot; rk[id[u]]=u;/*记录数组的第i个位置是编号为几的数*/ if(son[u]==-1) return ; dfs2(son[u],tp); for(int i=head[u]; ~i; i=e[i].next) { int v=e[i].to; if(v!=f[u]&&v!=son[u]) dfs2(v,v); }}/*线段树*/void pushup(int cur){ t[cur]=t[cur<<1]+t[cur<<1|1];}void pushdown(int cur,int l,int r){ int mid=(l+r)>>1; if(add[cur]) { add[cur<<1]+=add[cur]; add[cur<<1|1]+=add[cur]; t[cur<<1]+=add[cur]*(mid-l+1); t[cur<<1|1]+=add[cur]*(r-mid); add[cur]=0; }}void build(int cur,int l,int r){ add[cur]=0; if(l==r) { t[cur]=val[rk[l]]; return ; } int mid=(l+r)>>1; build(cur<<1,l,mid); build(cur<<1|1,mid+1,r);}void Update(int cur,int l,int r,int L,int R,int k){ if(L<=l&&R>=r) { add[cur]+=k; t[cur]+=(r-l+1)*k; return ; } pushdown(cur,l,r); int mid=(l+r)>>1; if(L<=mid) Update(cur<<1,l,mid,L,R,k); if(R>mid) Update(cur<<1|1,mid+1,r,L,R,k); pushup(cur);}int Query(int cur,int l,int r,int index){ int ans; if(l==r) return t[cur]; pushdown(cur,l,r); int mid=(l+r)>>1; if(index<=mid) ans=Query(cur<<1,l,mid,index); else ans=Query(cur<<1|1,mid+1,r,index); // pushup(cur); return ans;}void Change(int x,int y,int val){ while(top[x]!=top[y]) { if(d[top[x]]<d[top[y]]) swap(x,y); Update(1,1,n,id[top[x]],id[x],val); x=f[top[x]]; } if(d[x]>d[y]) swap(x,y); Update(1,1,n,id[x],id[y],val);}int main(){ int m,p,u,v,y,x,k; char s[110]; while(~scanf("%d%d%d",&n,&m,&p)) { Init(); for(int i=1; i<=n; i++) scanf("%d",&val[i]); for(int i=1; i<n; i++) { scanf("%d%d",&u,&v); addEdge(u,v); addEdge(v,u); } dfs1(1,0,1); dfs2(1,1); build(1,1,n); while(p--) { scanf("%s",s); if(s[0]=='Q') { scanf("%d",&x); printf("%d\n",Query(1,1,n,id[x])); } else { scanf("%d%d%d",&x,&y,&k); if(s[0]=='D') k=-k; Change(x,y,k); } } } return 0;}/*10 9 51 2 3 4 5 6 7 8 9 101 21 32 83 53 45 75 64 99 10*/
/*FZU 2082 更新边权*/#include <cstdio>#include <cstring>#include <algorithm>typedef long long LL;using namespace std;const int maxn=50010;struct node{ int to,next,w,id;} e[maxn<<1];int n,head[maxn],cnt,f[maxn],d[maxn],son[maxn],sz[maxn],val[maxn],ee[maxn],tot,top[maxn],id[maxn],rk[maxn];void Init(){ memset(head,-1,sizeof(head)); cnt=0; memset(son,-1,sizeof(son)); tot=0;}void add(int u,int v,int w,int id){ e[cnt].to=v; e[cnt].w=w; e[cnt].id=id; e[cnt].next=head[u]; head[u]=cnt++;}void dfs1(int u,int fa,int depth,int w,int pos){ f[u]=fa;/*记录父亲*/ d[u]=depth;/*记录深度*/ sz[u]=1;/*记录孩子个数,选择重边*/ val[u]=w;/*以u为终点的边的权值为w*/ ee[pos]=u;/*第pos条边的终点为u*/ for(int i=head[u]; ~i; i=e[i].next) { int v=e[i].to; if(v!=fa) { dfs1(v,u,depth+1,e[i].w,e[i].id); sz[u]+=sz[v]; if(son[u]==-1||sz[son[u]]<sz[v]) son[u]=v; } }}void dfs2(int u,int tp)/*将同一条链的结点映射到连续的一段区间[]*/{ top[u]=tp; id[u]=++tot; rk[id[u]]=u; if(son[u]==-1) return ; dfs2(son[u],tp); for(int i=head[u]; ~i; i=e[i].next) { int v=e[i].to; if(v!=f[u]&&v!=son[u]) dfs2(v,v); }}/*线段树 单点更新 区间查询*/LL t[maxn<<2];void pushup(int cur){ t[cur]=t[cur<<1]+t[cur<<1|1];}void build(int cur,int l,int r){ if(l==r) { t[cur]=val[rk[l]]; return ; } int mid=(l+r)>>1; build(cur<<1,l,mid); build(cur<<1|1,mid+1,r); pushup(cur);}void Update(int cur,int l,int r,int index,int k){ if(l==r) { t[cur]=k; return ; } int mid=(l+r)>>1; if(index<=mid) Update(cur<<1,l,mid,index,k); else Update(cur<<1|1,mid+1,r,index,k); pushup(cur);}LL Query(int cur,int l,int r,int L,int R){ LL ans=0; if(L<=l&&R>=r) { return t[cur]; } int mid=(l+r)>>1; if(L<=mid) ans+=Query(cur<<1,l,mid,L,R); if(R>mid) ans+=Query(cur<<1|1,mid+1,r,L,R); return ans;}void Change(int u,int v){ LL ans=0; while(top[u]!=top[v]) { if(d[top[u]]<d[top[v]]) swap(u,v); ans+=Query(1,1,n,id[top[u]],id[u]); u=f[top[u]]; } if(d[u]>d[v]) swap(u,v); ans+=Query(1,1,n,id[u]+1,id[v]); printf("%lld\n",ans);}int main(){ int m,u,v,w,op,x,y; while(~scanf("%d%d",&n,&m)) { Init(); for(int i=1; i<n; i++) { scanf("%d%d%d",&u,&v,&w); add(u,v,w,i); add(v,u,w,i); } dfs1(1,0,0,0,0); dfs2(1,1); build(1,1,n); while(m--) { scanf("%d%d%d",&op,&x,&y); if(op==0) { Update(1,1,n,id[ee[x]],y); } else { Change(x,y); } } } return 0;}
//BZOJ 1036 更新点权#include <bits/stdc++.h>#define INF 0x3f3f3f3fusing namespace std;const int maxn=30010;int val[maxn],n;int head[maxn],cnt,d[maxn],f[maxn],sz[maxn],son[maxn],id[maxn],tot,rk[maxn],top[maxn];struct node{ int to,next;} e[maxn<<1];struct pp{ int sum,Max;} t[maxn<<2];void Init(){ memset(head,-1,sizeof(head)); cnt=0; memset(son,-1,sizeof(son)); tot=0;}void addEdge(int u,int v){ e[cnt].to=v; e[cnt].next=head[u]; head[u]=cnt++;}void dfs1(int u,int fa,int depth){ d[u]=depth; f[u]=fa; sz[u]=1; for(int i=head[u]; ~i; i=e[i].next) { int v=e[i].to; if(v!=fa) { dfs1(v,u,depth+1); sz[u]+=sz[v]; if(son[u]==-1||sz[son[u]]<sz[v]) son[u]=v; } }}void dfs2(int u,int tp){ top[u]=tp; id[u]=++tot; rk[id[u]]=u; if(son[u]==-1) return ; dfs2(son[u],tp); for(int i=head[u]; ~i; i=e[i].next) { int v=e[i].to; if(v!=f[u]&&son[u]!=v) dfs2(v,v); }}void pushup(int cur){ t[cur].sum=t[cur<<1].sum+t[cur<<1|1].sum; t[cur].Max=max(t[cur<<1].Max,t[cur<<1|1].Max);}void build(int cur,int l,int r){ if(l==r) { t[cur].Max=t[cur].sum=val[rk[l]]; return ; } int mid=(l+r)>>1; build(cur<<1,l,mid); build(cur<<1|1,mid+1,r); pushup(cur);}void Update(int cur,int l,int r,int index,int k){ if(l==r) { t[cur].Max=t[cur].sum=k; return ; } int mid=(l+r)>>1; if(index<=mid) Update(cur<<1,l,mid,index,k); else Update(cur<<1|1,mid+1,r,index,k); pushup(cur);}int Query(int cur,int l,int r,int L,int R,int flag){ // printf("l = %d r = %d\n",l,r); int ans; if(flag) ans=-INF;/*数据权值有负数 之前设ans=0 WA*/ else ans=0; if(L<=l&&R>=r) { if(flag) return t[cur].Max; else return t[cur].sum; } int mid=(l+r)>>1; if(L<=mid) { if(flag) ans=max(ans,Query(cur<<1,l,mid,L,R,flag)); else ans+=Query(cur<<1,l,mid,L,R,flag); } if(R>mid) { if(flag) ans=max(ans,Query(cur<<1|1,mid+1,r,L,R,flag)); else ans+=Query(cur<<1|1,mid+1,r,L,R,flag); } return ans;//没返回值 debug了好久。。}void Change(int u,int v,int flag){ int ans; if(flag) ans=-INF; else ans=0; while(top[u]!=top[v]) { if(d[top[u]]<d[top[v]]) swap(u,v); if(flag)ans=max(ans,Query(1,1,n,id[top[u]],id[u],flag)); else ans+=Query(1,1,n,id[top[u]],id[u],flag); u=f[top[u]]; } if(d[u]>d[v]) swap(u,v); if(flag) ans=max(ans,Query(1,1,n,id[u],id[v],flag)); else ans+=Query(1,1,n,id[u],id[v],flag); printf("%d\n",ans);}int main(){ int u,v,x,y,q; char s[110]; scanf("%d",&n); Init(); for(int i=1; i<n; i++) { scanf("%d%d",&u,&v); addEdge(u,v); addEdge(v,u); } for(int i=1; i<=n; i++) scanf("%d",&val[i]); dfs1(1,0,0); dfs2(1,1); // build(1,1,n); scanf("%d",&q); while(q--) { scanf("%s",s); if(s[0]=='C') { scanf("%d%d",&x,&y); Update(1,1,n,id[x],y); } else { scanf("%d%d",&x,&y); if(s[1]=='M') Change(x,y,1); else Change(x,y,0); } } return 0;}
0 0