[HAOI2015]树上操作 -树链剖分
1963. [HAOI2015]树上操作
【题目描述】
有一棵点数为N的树,以点1为根,且树点有权值。然后有M个操作,分为三种:
操作1:把某个节点x的点权增加a。
操作2:把某个节点x为根的子树中所有点的点权都增加a。
操作3:询问某个节点x到根的路径中所有点的点权和。
【输入格式】
第一行两个整数N,M,表示点数和操作数。
接下来一行N个整数,表示树中节点的初始权值。
接下来N-1行每行两个正整数fr,to,表示该树中存在一条边(fr,to)。
再接下来M行,每行分别表示一次操作。其中第一个数表示该操作的种类(1~3),之后接这个操作的参数(x或者x a)。
【输出格式】
对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
【样例输入】
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
【样例输出】
6
9
13
【提示】
对于30%的数据,N,M<=1000
对于50%的数据,N,M<=100000且数据随机。
对于100%的数据,N,M<=100000,且所有输入数据的绝对值都不会超过10^6。
注意long long就好了
把它当做树剖模板来做,听说并查集也能做
1 #include <ctype.h> 2 #include <cstdio> 3 4 typedef long long LL; 5 6 const int MAXN=100010; 7 8 int n,m,inr; 9 10 LL a[MAXN]; 11 12 struct SegmentTree { 13 int l,r; 14 LL val,tag; 15 }; 16 SegmentTree t[MAXN<<2]; 17 18 struct data { 19 int to; 20 int next; 21 }; 22 data E[MAXN*10]; 23 24 int head[MAXN<<1],tot; 25 26 int siz[MAXN],son[MAXN],fa[MAXN],id[MAXN],dep[MAXN],top[MAXN],rank[MAXN],mx[MAXN]; 27 28 inline void read(int&x) { 29 int f=1;register char c=getchar(); 30 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 31 for(;isdigit(c);x=x*10+c-48,c=getchar()); 32 x=x*f; 33 } 34 35 inline void readl(LL&x) { 36 int f=1;register char c=getchar(); 37 for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar()); 38 for(;isdigit(c);x=x*10+c-48,c=getchar()); 39 x=x*f; 40 } 41 42 inline void add(int x,int y) { 43 E[++tot].to=y; 44 E[tot].next=head[x]; 45 head[x]=tot; 46 } 47 48 inline int max(int a,int b) { 49 return a<b?b:a; 50 } 51 52 inline void swap(int&x,int&y) { 53 int t=x;x=y;y=t; 54 return; 55 } 56 57 inline void dfs_1(int now,int f) { 58 dep[now]=dep[f]+1; 59 siz[now]=1; 60 fa[now]=f; 61 for(register int i=head[now];i;i=E[i].next) { 62 int to=E[i].to; 63 if(to==f) continue; 64 dfs_1(to,now); 65 siz[now]+=siz[to]; 66 if(son[now]==-1||siz[son[now]]<siz[to]) son[now]=to; 67 } 68 } 69 70 inline void dfs_2(int now,int sym) { 71 id[now]=++inr; 72 top[now]=sym; 73 rank[id[now]]=now; 74 if(son[now]==-1) return; 75 dfs_2(son[now],sym); 76 for(int i=head[now];i;i=E[i].next) { 77 int to=E[i].to; 78 if(to!=son[now]&&to!=fa[now]) 79 dfs_2(to,to); 80 } 81 return; 82 } 83 84 inline void build_tree(int now,int l,int r) { 85 t[now].l=l,t[now].r=r; 86 if(l==r) { 87 t[now].val=a[rank[l]]; 88 return; 89 } 90 int mid=(l+r)>>1; 91 build_tree(now<<1,l,mid); 92 build_tree(now<<1|1,mid+1,r); 93 t[now].val=t[now<<1].val+t[now<<1|1].val; 94 } 95 96 inline void down(int now) { 97 t[now<<1].val+=(t[now<<1].r-t[now<<1].l+1)*t[now].tag; 98 t[now<<1|1].val+=(t[now<<1|1].r-t[now<<1|1].l+1)*t[now].tag; 99 t[now<<1].tag+=t[now].tag; 100 t[now<<1|1].tag+=t[now].tag; 101 t[now].tag=0; 102 } 103 104 inline void modify(int now,int l,int r,LL val) { 105 if(l<=t[now].l&&r>=t[now].r) { 106 t[now].tag+=val; 107 t[now].val+=(t[now].r-t[now].l+1)*val; 108 return; 109 } 110 down(now); 111 int mid=(t[now].l+t[now].r)>>1; 112 if(l<=mid) modify(now<<1,l,r,val); 113 if(r>mid) modify(now<<1|1,l,r,val); 114 t[now].val=t[now<<1].val+t[now<<1|1].val; 115 } 116 117 inline LL query(int now,int l,int r) { 118 LL ans=0; 119 if(l<=t[now].l&&r>=t[now].r) return t[now].val; 120 down(now); 121 int mid=(t[now].l+t[now].r)>>1; 122 if(l<=mid) ans+=query(now<<1,l,r); 123 if(r>mid) ans+=query(now<<1|1,l,r); 124 return ans; 125 } 126 127 inline LL Pre_query(int u,int v) { 128 LL ans=0; 129 while(top[u]!=top[v]) { 130 if(dep[top[u]]<dep[top[v]]) swap(u,v); 131 ans+=query(1,id[top[u]],id[u]); 132 u=fa[top[u]]; 133 } 134 if(dep[u]<dep[v]) swap(u,v); 135 ans+=query(1,id[v],id[u]); 136 return ans; 137 } 138 139 int hh() { 140 freopen("haoi2015_t2.in","r",stdin); 141 freopen("haoi2015_t2.out","w",stdout); 142 int x,y,opt; 143 read(n);read(m); 144 for(register int i=1;i<=n;++i) son[i]=-1,readl(a[i]); 145 for(register int i=1;i<n;++i) { 146 read(x);read(y); 147 add(x,y);add(y,x); 148 } 149 dfs_1(1,0); 150 dfs_2(1,1); 151 build_tree(1,1,inr); 152 LL p; 153 for(register int i=1;i<=m;++i) { 154 read(opt);read(x); 155 if(opt==1) { 156 readl(p); 157 modify(1,id[x],id[x],p); 158 } 159 else if(opt==2) { 160 readl(p); 161 modify(1,id[x],id[x]+siz[x]-1,p); 162 } 163 else { 164 LL ans=Pre_query(1,x); 165 printf("%lld\n",ans); 166 } 167 } 168 return 0; 169 } 170 171 int sb=hh(); 172 int main() {;}
作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现
怎么能够停止不前
穿越时空 竭尽全力
我会来到你身边
微笑面对危险
梦想成真不会遥远
鼓起勇气 坚定向前
奇迹一定会出现