bzoj4034: [HAOI2015]T2
开始可以过样例,然而交一直WA。肉眼差错=0,拿小数据写暴力对拍果然拍出错了,改!大数据!拍!没错了。交!WA。。。又把题面看了几遍,瞄到一个绝对值什么的嗤笑一声逗我树节点的权值怎么会是负的。于是半小时后突然想到为什么不能是负的。。。就A了。。。细节细节不要太多理所当然。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,n) for(int i=1;i<=n;i++) #define clr(x,c) memset(x,c,sizeof(x)) #define qwq(x) for(edge *o=head[x];o;o=o->next) #define op() clr(head,0);pt=edges; #define lson l,m,x<<1 #define rson m+1,r,x<<1|1 #define adde(u,v) add(u,v),add(v,u) #define ll long long int read(){ int x=0;char c=getchar();bool f=true; while(!isdigit(c)) { if(c=='-') f=false; c=getchar(); } while (isdigit(c)) x=x*10+c-'0',c=getchar(); return f?x:-x; } const int nmax=100005; const int inf=0x7f7f7f7f; struct edge{ int to;edge *next; }; edge edges[nmax<<1],*pt,*head[nmax]; int son[nmax],size[nmax],dep[nmax],id[nmax],idx[nmax<<2],tp[nmax],fa[nmax],w[nmax],lft[nmax],rht[nmax],n; ll sum[nmax<<2],col[nmax<<2]; void add(int u,int v){ pt->to=v;pt->next=head[u];head[u]=pt++; } void dfs(int x,int father){ size[x]=1; qwq(x){ int to=o->to; if(to==father) continue; dep[to]=dep[x]+1;fa[to]=x;dfs(to,x); size[x]+=size[to]; if(!son[x]||size[to]>size[son[x]]) son[x]=to; } } void Dfs(int x,int top){ id[x]=++id[0];idx[id[0]]=x;lft[x]=id[0];tp[x]=top; if(son[x]) Dfs(son[x],top); qwq(x) if(!id[o->to]) Dfs(o->to,o->to); rht[x]=id[0]; } void build(int l,int r,int x){ if(l==r) { sum[x]=w[idx[l]];return ; } int m=(l+r)>>1;build(lson);build(rson);sum[x]=sum[x<<1]+sum[x<<1|1]; } void pushdown(int x,int tmp){ if(col[x]){ sum[x<<1]+=col[x]*(tmp-(tmp>>1));sum[x<<1|1]+=col[x]*(tmp>>1); col[x<<1]+=col[x];col[x<<1|1]+=col[x];col[x]=0; } } void update(int tl,int tr,int add,int l,int r,int x){ if(tl<=l&&tr>=r){ sum[x]+=(ll)add*(r-l+1);col[x]+=add;return ; } pushdown(x,r-l+1); int m=(l+r)>>1; if(tl<=m) update(tl,tr,add,lson); if(tr>m) update(tl,tr,add,rson); sum[x]=sum[x<<1]+sum[x<<1|1]; } ll query(int tl,int tr,int l,int r,int x){ if(tl<=l&&tr>=r) return sum[x]; pushdown(x,r-l+1); int m=(l+r)>>1;ll ans=0; if(tl<=m) ans+=query(tl,tr,lson); if(tr>m) ans+=query(tl,tr,rson); return ans; } ll qsum(int a,int b){ ll ans=0; while(tp[a]!=tp[b]) { ans+=query(id[tp[b]],id[b],1,n,1); b=fa[tp[b]]; //printf("%d ",tp[b]); } //printf("\n"); ans+=query(id[a],id[b],1,n,1); return ans; } int main(){ /*freopen("data.out","r",stdin); freopen("4034.out","w",stdout);*/ op(); n=read();int m=read(),u,v,d; rep(i,n) w[i]=read(); rep(i,n-1) u=read(),v=read(),adde(u,v); clr(fa,0);clr(son,0);dep[1]=0; clr(id,0); dfs(1,-1); //rep(i,n) printf("%d:%d %d %d %d\n",i,fa[i],size[i],son[i],dep[i]); Dfs(1,1); //rep(i,n) printf("%d ",id[i]);printf("\n"); //rep(i,n) printf("%d ",tp[i]); build(1,n,1); rep(i,m){ u=read(); if(u==1) v=read(),d=read(),update(id[v],id[v],d,1,n,1); else if(u==2) v=read(),d=read(),update(lft[v],rht[v],d,1,n,1); else v=read(),printf("%lld\n",qsum(1,v)); } return 0; }
4034: [HAOI2015]T2
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2654 Solved: 835
[Submit][Status][Discuss]
Description
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个
操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
Input
第一行包含两个整数 N, M 。表示点数和操作数。
接下来一行 N 个整数,表示树中节点的初始权值。
接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。
再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操
作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。
Output
对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
Sample Input
5 5
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3
Sample Output
6
9
13
9
13
HINT
对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不
会超过 10^6 。