1. 程式人生 > >[國家集訓隊2012]tree(伍一鳴)

[國家集訓隊2012]tree(伍一鳴)

char fine spa itl psr 接下來 play ons ast

[國家集訓隊2012]tree(伍一鳴)

tree(伍一鳴) 時間限制:2.5s 內存限制:64.0M

【問題描述】

一棵n個點的樹,每個點的初始權值為1。對於這棵樹有q個操作,每個操作為以下四種操作之一:
+ u v c:將u到v的路徑上的點的權值都加上自然數c;
- u1 v1 u2 v2:將樹中原有的邊(u1,v1)刪除,加入一條新邊(u2,v2),保證操作完之後仍然是一棵樹;
* u v c:將u到v的路徑上的點的權值都乘上自然數c;
/ u v:詢問u到v的路徑上的點的權值和,求出答案對於51061的余數。

【輸入格式】

第一行兩個整數n,q
接下來n-1行每行兩個正整數u,v,描述這棵樹
接下來q行,每行描述一個操作

【輸出格式】

對於每個/對應的答案輸出一行

【樣例輸入】

3 2
1 2
2 3
* 1 3 4
/ 1 1

【樣例輸出】

4

【數據規模和約定】

10%的數據保證,1<=n,q<=2000
另外15%的數據保證,1<=n,q<=5*10^4,沒有-操作,並且初始樹為一條鏈
另外35%的數據保證,1<=n,q<=5*10^4,沒有-操作
100%的數據保證,1<=n,q<=10^5,0<=c<=10^4 繼續水板子... 感覺已經蠻熟練了... 技術分享圖片
  1 #include<bits/stdc++.h>
  2
#define ll long long 3 using namespace std; 4 const int mod=51061; 5 const int inf=1e5+5; 6 int n,q,tot,fi[inf],to[inf<<1],next[inf<<1]; 7 int ch[inf][2],fa[inf],rev[inf],siz[inf]; 8 ll add[inf],mul[inf],sum[inf],v[inf]; 9 void edge_add(int x,int y){ 10 to[++tot]=y;
11 next[tot]=fi[x]; 12 fi[x]=tot; 13 } 14 void dfs(int x,int f){ 15 fa[x]=f; 16 siz[x]=1; 17 v[x]=1; 18 mul[x]=1; 19 add[x]=0; 20 sum[x]=1; 21 for(int i=fi[x];i;i=next[i]) 22 if(to[i]!=f)dfs(to[i],x); 23 } 24 bool get(int x){ 25 return ch[fa[x]][1]==x; 26 } 27 bool isroot(int x){ 28 return ch[fa[x]][1]!=x&&ch[fa[x]][0]!=x; 29 } 30 void update(int x){ 31 int ls=ch[x][0],rs=ch[x][1]; 32 siz[x]=siz[ls]+siz[rs]+1; 33 sum[x]=(sum[ls]+sum[rs]+v[x])%mod; 34 } 35 void pushdown(int x){ 36 int ls=ch[x][0],rs=ch[x][1]; 37 if(rev[x]){ 38 rev[x]=0; 39 rev[ls]^=1; 40 rev[rs]^=1; 41 swap(ch[ls][0],ch[ls][1]); 42 swap(ch[rs][0],ch[rs][1]); 43 } 44 v[x]=(v[x]*mul[x]+add[x])%mod; 45 mul[ls]=mul[ls]*mul[x]%mod; 46 mul[rs]=mul[rs]*mul[x]%mod; 47 add[ls]=(mul[x]*add[ls]+add[x])%mod; 48 add[rs]=(mul[x]*add[rs]+add[x])%mod; 49 sum[ls]=(sum[ls]*mul[x]+add[x]*siz[ls])%mod; 50 sum[rs]=(sum[rs]*mul[x]+add[x]*siz[rs])%mod; 51 add[x]=0;mul[x]=1; 52 } 53 void zig(int x){ 54 int old=fa[x],oldf=fa[old]; 55 pushdown(old); 56 pushdown(x); 57 bool p=get(x); 58 if(!isroot(old))ch[oldf][get(old)]=x; 59 fa[x]=oldf; 60 fa[ch[old][p]=ch[x][p^1]]=old; 61 fa[ch[x][p^1]=old]=x; 62 update(old); 63 update(x); 64 } 65 void splay(int x){ 66 for(;!isroot(x);zig(x)) 67 if(!isroot(fa[x]))zig(get(x)==get(fa[x])?fa[x]:x); 68 pushdown(x);//防止單獨一個點成splay標記未下傳 69 } 70 void access(int x){ 71 int last=0; 72 while(x){ 73 splay(x); 74 ch[x][1]=last; 75 update(x); 76 last=x; 77 x=fa[x]; 78 } 79 } 80 void makeroot(int x){ 81 access(x); 82 splay(x); 83 rev[x]^=1; 84 swap(ch[x][0],ch[x][1]); 85 } 86 void cut(int x,int y){ 87 makeroot(x); 88 access(y); 89 splay(y); 90 ch[y][0]=fa[x]=0; 91 update(y); 92 } 93 void link(int x,int y){ 94 makeroot(x); 95 fa[x]=y; 96 } 97 void Add(int x,int y,int z){ 98 makeroot(x); 99 access(y); 100 splay(y); 101 add[y]=(add[y]+z)%mod; 102 sum[y]=(sum[y]+z*siz[y])%mod; 103 } 104 void Mul(int x,int y,int z){ 105 makeroot(x); 106 access(y); 107 splay(y); 108 add[y]=add[y]*z%mod; 109 mul[y]=mul[y]*z%mod; 110 sum[y]=sum[y]*z%mod; 111 } 112 int Q(int x,int y){ 113 makeroot(x); 114 access(y); 115 splay(y); 116 return sum[y]; 117 } 118 int main() 119 { 120 scanf("%d%d",&n,&q); 121 for(int i=1;i<n;i++){ 122 int x,y; 123 scanf("%d%d",&x,&y); 124 edge_add(x,y);edge_add(y,x); 125 } 126 dfs(1,0); 127 for(int i=1;i<=q;i++){ 128 char c; 129 cin>>c; 130 if(c==+){ 131 int u,v,c; 132 scanf("%d%d%d",&u,&v,&c); 133 Add(u,v,c); 134 } 135 else if(c==-){ 136 int u1,v1,u2,v2; 137 scanf("%d%d%d%d",&u1,&v1,&u2,&v2); 138 cut(u1,v1); 139 link(u2,v2); 140 } 141 else if(c==*){ 142 int u,v,c; 143 scanf("%d%d%d",&u,&v,&c); 144 Mul(u,v,c); 145 } 146 else if(c==/){ 147 int x,y; 148 scanf("%d%d",&x,&y); 149 printf("%d\n",Q(x,y)); 150 } 151 } 152 return 0; 153 }
View Code

[國家集訓隊2012]tree(伍一鳴)