HDU-3966-树链剖分

来源:互联网 发布:ps4 刀剑神域 知乎 编辑:程序博客网 时间:2024/06/05 03:08

题目大意:给定一棵树,两两种操作,一种是询问v,u所有节点的sum,还有一种是修改u到v上所有路径的val;

题目解析:裸的树链剖分;

AC代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<string>#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1using namespace std;const int maxn=50010;struct edge{int to,next;}e[maxn<<1];int head[maxn],tot;int num[maxn];//叶子节点的值 int size[maxn];//儿子个数 int top[maxn];//当前节点所在链的顶端节点 int son[maxn];//重儿子 int dep[maxn];//深度 int tid[maxn];//被树剖之后的新编号 int rak[maxn];//当前节点在线段树间的位置 int fa[maxn];//父亲int tim; void init(){memset(head,-1,sizeof(head));memset(son,-1,sizeof(son));tim=0;tot=0;}void addedge(int u,int v){e[tot].to=v;e[tot].next=head[u];head[u]=tot++;e[tot].to=u;e[tot].next=head[v];head[v]=tot++;}void dfs1(int u,int father,int d){dep[u]=d;fa[u]=father;size[u]=1;for(int i=head[u];~i;i=e[i].next){int v=e[i].to;if(v!=father){dfs1(v,u,d+1);size[u]+=size[v];if(son[u]==-1||size[v]>size[son[u]])son[u]=v;}}}void dfs2(int u,int tp){top[u]=tp;tid[u]=++tim;rak[tid[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!=son[u]&&v!=fa[u]){dfs2(v,v);}}}//线段树int sum[maxn<<2],col[maxn<<2],n,m,q;void pushup(int rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void pushdown(int rt,int m){if(col[rt]){col[rt<<1]+=col[rt];col[rt<<1|1]+=col[rt];sum[rt<<1]+=(m-(m>>1))*col[rt];sum[rt<<1|1]+=(m>>1)*col[rt];col[rt]=0;}}void build(int l,int r,int rt){col[rt]=0;if(l==r){sum[rt]=num[rak[l]];return ;}int mid=(l+r)>>1;build(lson);build(rson);pushup(rt);}void update(int le,int ri,int v,int l,int r,int rt){//cout<<le<<" "<<ri<<" "<<l<<" "<<r<<endl;if(le<=l&&ri>=r){col[rt]+=v;sum[rt]+=v*(r-l+1);return ;}pushdown(rt,r-l+1);int mid=(l+r)>>1;int ret=0;if(le<=mid)update(le,ri,v,lson);if(ri>mid)update(le,ri,v,rson);pushup(rt);}int query(int le,int ri,int l,int r,int rt){if(le<=l&&ri>=r)return sum[rt];pushdown(rt,r-l+1);int mid=(l+r)>>1;int ret=0;if(le<=mid)ret+=query(le,ri,lson);if(ri>mid)ret+=query(le,ri,rson);pushup(rt);return ret;}void change(int x,int y,int val){while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);update(tid[top[x]],tid[x],val,1,n,1);x=fa[top[x]];}if(dep[x]>dep[y])swap(x,y);update(tid[x],tid[y],val,1,n,1);}int main(){char op[5];int a,b,c;while(scanf("%d%d%d",&n,&m,&q)!=EOF){init();for(int i=1;i<=n;i++)scanf("%d",&num[i]);for(int i=1;i<=m;i++){scanf("%d%d",&a,&b);addedge(a,b);}dfs1(1,0,0);dfs2(1,1);build(1,n,1);while(q--){scanf("%s",&op[0]);if(op[0]=='Q'){scanf("%d",&a);printf("%d\n",query(tid[a],tid[a],1,n,1));}else {scanf("%d%d%d",&a,&b,&c);if(op[0]=='D'){c=-c;}change(a,b,c);}}}return 0;}


原创粉丝点击