[BZOJ1984] 月下“毛景树”
Description
毛毛蟲經(jīng)過及時的變形,最終逃過的一劫,離開了菜媽的菜園。 毛毛蟲經(jīng)過千山萬水,歷盡千辛萬苦,最后來到了小小的紹興一中的校園里。爬啊爬~爬啊爬~~毛毛蟲爬到了一顆小小的“毛景樹”下面,發(fā)現(xiàn)樹上長著他最愛吃的毛毛果~~~ “毛景樹”上有N個節(jié)點和N-1條樹枝,但節(jié)點上是沒有毛毛果的,毛毛果都是長在樹枝上的。但是這棵“毛景樹”有著神奇的魔力,他能改變樹枝上毛毛果的個數(shù): ? Change k w:將第k條樹枝上毛毛果的個數(shù)改變?yōu)閣個。 ? Cover u v w:將節(jié)點u與節(jié)點v之間的樹枝上毛毛果的個數(shù)都改變?yōu)閣個。 ? Add u v w:將節(jié)點u與節(jié)點v之間的樹枝上毛毛果的個數(shù)都增加w個。 由于毛毛蟲很貪,于是他會有如下詢問: ? Max u v:詢問節(jié)點u與節(jié)點v之間樹枝上毛毛果個數(shù)最多有多少個。
Input
第一行一個正整數(shù)N。 接下來N-1行,每行三個正整數(shù)Ui,Vi和Wi,第i+1行描述第i條樹枝。表示第i條樹枝連接節(jié)點Ui和節(jié)點Vi,樹枝上有Wi個毛毛果。 接下來是操作和詢問,以“Stop”結(jié)束。
Output
對于毛毛蟲的每個詢問操作,輸出一個答案。
Sample Input
41 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
916
【Data Range】
1<=N<=100,000,操作+詢問數(shù)目不超過100,000。
保證在任意時刻,所有樹枝上毛毛果的個數(shù)都不會超過10^9個
思路
樹鏈剖分+線段樹; 注意是邊權(quán)代碼實現(xiàn)
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 }?我代碼常數(shù)巨大,您怕不怕?
| 1984 | Accepted | 14180 kb | 4284 ms | C++/Edit | 3716 B | 2017-06-10 15:01:51 |
轉(zhuǎn)載于:https://www.cnblogs.com/J-william/p/6978811.html
總結(jié)
以上是生活随笔為你收集整理的[BZOJ1984] 月下“毛景树”的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PyCharm使用指南及更改Python
- 下一篇: 洛谷P2826 [USACO08NOV]