bzoj4034: [HAOI2015]T2

来源:互联网 发布:邮箱大师mac下载 编辑:程序博客网 时间:2024/05/17 23:06

初学树剖。。。听说是裸题。。。然后就做了。。。

注意某个节点和它的子树DFS序相连,只要记住它子树最大的DFS序即可进行子树修改。

#include<iostream>#include<cstdio>#define N 2000000#define ll long longusing namespace std;int n,m,x,y,l,p,q;ll s[N*5],up;struct edge{int to,next;}k[N];struct node{int first,size,fa,mx,head,o;ll v,fl;}a[N];void link(int x,int y){k[++l]=(edge){y,a[x].first};a[x].first=l;k[++l]=(edge){x,a[y].first};a[y].first=l;}void dfs1(int x){a[x].size=1;for(int i=a[x].first;i;i=k[i].next)if(k[i].to!=a[x].fa){a[k[i].to].fa=x;dfs1(k[i].to);a[x].size+=a[k[i].to].size;}}void dfs2(int x,int t){a[x].head=t;a[x].o=a[x].mx=++p;int M=0;for(int i=a[x].first;i;i=k[i].next)if(k[i].to!=a[x].fa&&a[k[i].to].size>a[M].size)M=k[i].to;if(M)dfs2(M,t),a[x].mx=max(a[x].mx,a[M].mx);for(int i=a[x].first;i;i=k[i].next)if(k[i].to!=a[x].fa&&k[i].to!=M)dfs2(k[i].to,k[i].to),a[x].mx=max(a[x].mx,a[k[i].to].mx);}void push(int l,int r,int t){if(l==r)return;int mid=(l+r)>>1;a[t<<1].fl+=a[t].fl;s[t<<1]+=a[t].fl*(mid-l+1);a[t<<1|1].fl+=a[t].fl;s[t<<1|1]+=a[t].fl*(r-mid);a[t].fl=0;}void add(int t,int l,int r,ll up){if(a[t].fl)push(l,r,t);if(x<=l&&r<=y){a[t].fl+=up;s[t]+=(r-l+1)*up;return;}int mid=(l+r)>>1;if(x<=mid)add(t<<1,l,mid,up);if(y>mid)add(t<<1|1,mid+1,r,up);s[t]=s[t<<1]+s[t<<1|1];}ll Qu(int t,int l,int r,int x,int y){if(a[t].fl)push(l,r,t);if(x<=l&&r<=y)return s[t];ll Ans=0;int mid=(l+r)>>1;if(x<=mid)Ans+=Qu(t<<1,l,mid,x,y);if(y>mid)Ans+=Qu(t<<1|1,mid+1,r,x,y);return Ans;}ll Q(int x){ll Ans=0;for(;a[x].head!=1;x=a[a[x].head].fa)Ans+=Qu(1,1,n,a[a[x].head].o,a[x].o);Ans+=Qu(1,1,n,1,a[x].o);return Ans;}int main()  { scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%lld",&a[i].v);for(int i=1;i<n;i++)scanf("%d%d",&x,&y),link(x,y);dfs1(1);dfs2(1,1);for(int i=1;i<=n;i++) x=y=a[i].o,add(1,1,n,a[i].v);for(int i=1;i<=m;i++){scanf("%d%d",&q,&p);if(q==1)scanf("%lld",&up),x=a[p].o,y=a[p].o,add(1,1,n,up);if(q==2)scanf("%lld",&up),x=a[p].o,y=a[p].mx,add(1,1,n,up);if(q==3)printf("%lld\n",Q(p));}return 0;}


0 0
原创粉丝点击