[BZOJ1984] 月下“毛景树”
Posted 鄉勇
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ1984] 月下“毛景树”相关的知识,希望对你有一定的参考价值。
Description
毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数: ? Change k w:将第k条树枝上毛毛果的个数改变为w个。 ? Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。 ? Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问: ? Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。
Input
第一行一个正整数N。 接下来N-1行,每行三个正整数Ui,Vi和Wi,第i+1行描述第i条树枝。表示第i条树枝连接节点Ui和节点Vi,树枝上有Wi个毛毛果。 接下来是操作和询问,以“Stop”结束。
Output
对于毛毛虫的每个询问操作,输出一个答案。
Sample Input
4
1 2 8
1 3 7
3 4 9
Max 2 4
Cover 2 4 5
Add 1 4 10
Change 1 16
Max 2 4
Stop
1 2 8
1 3 7
3 4 9
Max 2 4
Cover 2 4 5
Add 1 4 10
Change 1 16
Max 2 4
Stop
Sample Output
9
16
【Data Range】
1<=N<=100,000,操作+询问数目不超过100,000。
保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个
16
【Data Range】
1<=N<=100,000,操作+询问数目不超过100,000。
保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个
思路
树链剖分+线段树;
注意是边权
代码实现
1 #include<cstdio> 2 const int maxn=1e5+10; 3 inline int min_(int x,int y){return x<y?x:y;} 4 inline int max_(int x,int y){return x>y?x:y;} 5 inline void swap_(int&x,int&y){x^=y,y^=x,x^=y;} 6 int n; 7 int a,b,c; 8 int s[maxn],ss,ts[maxn<<2],tl[maxn<<2],tf[maxn<<2]; 9 int ps[maxn],pd[maxn],pf[maxn],pt[maxn],pp[maxn],pps,psz[maxn],pws[maxn]; 10 int h[maxn],ep[maxn],hs,et[maxn<<1],es[maxn<<1],en[maxn<<1],eid[maxn<<1]; 11 void dfs1(int k,int f,int d){ 12 pd[k]=d,pf[k]=f,psz[k]=1; 13 for(int i=h[k];i;i=en[i]) 14 if(et[i]!=f){ 15 dfs1(et[i],k,d+1); 16 psz[k]+=psz[et[i]],ps[et[i]]=es[i],ep[eid[i]]=et[i]; 17 if(psz[et[i]]>psz[pws[k]]) pws[k]=et[i]; 18 } 19 } 20 void dfs2(int k,int t){ 21 s[++pps]=ps[k],pp[k]=pps,pt[k]=t; 22 if(pws[k]) dfs2(pws[k],t); 23 for(int i=h[k];i;i=en[i]) 24 if(et[i]!=pf[k]&&et[i]!=pws[k]){ 25 dfs2(et[i],et[i]); 26 } 27 } 28 void build(int k,int l,int r){ 29 if(l==r){ts[k]=s[++ss];return;} 30 int mid=l+r>>1,ls=k<<1,rs=ls|1; 31 build(ls,l,mid); 32 build(rs,mid+1,r); 33 ts[k]=max_(ts[ls],ts[rs]); 34 } 35 void downl(int k,int ls,int rs){ 36 tf[ls]=tf[rs]=0; 37 ts[ls]=ts[rs]=tl[ls]=tl[rs]=tl[k]; 38 tl[k]=0; 39 } 40 void downf(int k,int ls,int rs){ 41 ts[ls]+=tf[k],ts[rs]+=tf[k]; 42 tf[ls]+=tf[k],tf[rs]+=tf[k]; 43 tf[k]=0; 44 } 45 void change(int k,int l,int r,int al,int ar,int v){ 46 if(l==al&&r==ar){ts[k]=tl[k]=v,tf[k]=0;return;} 47 int mid=l+r>>1,ls=k<<1,rs=ls|1; 48 if(tl[k]) downl(k,ls,rs); 49 if(tf[k]) downf(k,ls,rs); 50 if(al<=mid) change(ls,l,mid,al,min_(ar,mid),v); 51 if(ar>mid) change(rs,mid+1,r,max_(al,mid+1),ar,v); 52 ts[k]=max_(ts[ls],ts[rs]); 53 } 54 void add(int k,int l,int r,int al,int ar,int v){ 55 if(l==al&&r==ar){ts[k]+=v,tf[k]+=v;return;} 56 int mid=l+r>>1,ls=k<<1,rs=ls|1; 57 if(tl[k]) downl(k,ls,rs); 58 if(tf[k]) downf(k,ls,rs); 59 if(al<=mid) add(ls,l,mid,al,min_(ar,mid),v); 60 if(ar>mid) add(rs,mid+1,r,max_(al,mid+1),ar,v); 61 ts[k]=max_(ts[ls],ts[rs]); 62 } 63 int query(int k,int l,int r,int al,int ar){ 64 if(l==al&&r==ar) return ts[k]; 65 int mid=l+r>>1,ls=k<<1,rs=ls|1,ret=0; 66 if(tl[k]) downl(k,ls,rs); 67 if(tf[k]) downf(k,ls,rs); 68 if(al<=mid) ret=max_(ret,query(ls,l,mid,al,min_(ar,mid))); 69 if(ar>mid) ret=max_(ret,query(rs,mid+1,r,max_(al,mid+1),ar)); 70 return ret; 71 } 72 int main(){ 73 scanf("%d",&n); 74 for(int i=1;i<n;i++){ 75 scanf("%d%d%d",&a,&b,&c); 76 ++hs,et[hs]=b,es[hs]=c,eid[hs]=i,en[hs]=h[a],h[a]=hs; 77 ++hs,et[hs]=a,es[hs]=c,eid[hs]=i,en[hs]=h[b],h[b]=hs; 78 } 79 dfs1(1,1,1); 80 dfs2(1,1); 81 build(1,1,n); 82 char ch[10]; 83 while(scanf("%s",ch)!=EOF){ 84 if(ch[0]==‘C‘){ 85 if(ch[1]==‘h‘){ 86 scanf("%d%d",&a,&b); 87 change(1,1,n,pp[ep[a]],pp[ep[a]],b); 88 } 89 if(ch[1]==‘o‘){ 90 scanf("%d%d%d",&a,&b,&c); 91 while(pt[a]!=pt[b]){ 92 if(pd[pt[a]]<pd[pt[b]]) swap_(a,b); 93 change(1,1,n,pp[pt[a]],pp[a],c); 94 a=pf[pt[a]]; 95 } 96 if(pd[a]>pd[b]) swap_(a,b); 97 if(pp[b]>pp[a]) change(1,1,n,pp[a]+1,pp[b],c); 98 } 99 } 100 if(ch[0]==‘A‘){ 101 scanf("%d%d%d",&a,&b,&c); 102 while(pt[a]!=pt[b]){ 103 if(pd[pt[a]]<pd[pt[b]]) swap_(a,b); 104 add(1,1,n,pp[pt[a]],pp[a],c); 105 a=pf[pt[a]]; 106 } 107 if(pd[a]>pd[b]) swap_(a,b); 108 if(pp[b]>pp[a]) add(1,1,n,pp[a]+1,pp[b],c); 109 } 110 if(ch[0]==‘M‘){ 111 scanf("%d%d",&a,&b),c=0; 112 while(pt[a]!=pt[b]){ 113 if(pd[pt[a]]<pd[pt[b]]) swap_(a,b); 114 c=max_(c,query(1,1,n,pp[pt[a]],pp[a])); 115 a=pf[pt[a]]; 116 } 117 if(pd[a]>pd[b]) swap_(a,b); 118 if(pp[b]>pp[a]) c=max_(c,query(1,1,n,pp[a]+1,pp[b])); 119 printf("%d\n",c); 120 } 121 if(ch[0]==‘S‘) return 0; 122 } 123 }
我代码常数巨大,您怕不怕?
1984 | Accepted | 14180 kb | 4284 ms | C++/Edit | 3716 B | 2017-06-10 15:01:51 |
以上是关于[BZOJ1984] 月下“毛景树”的主要内容,如果未能解决你的问题,请参考以下文章