[洛谷P1501] [国家集训队] Tree II
比之前那道LCT裸题难了一点儿。
这道题除了维护树的形态和连通性,还要维护点权了。
所以记录size、sum什么的,跟splay差不多。
lazy_tag、pushup、pushdown什么的,跟线段树差不多。
就是一道大杂烩嘛......
各种乱搞。
这里不再写cut(x,y)函数了,而是写了isolate(x,y)函数。
意为把从x到y的链单独提取到一个splay里面。
再加个删除父子关系不就是cut了嘛。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define M 51061 5 #define ll long long 6 #define id(x) (s[f[x]][1]==x) 7 using namespace std; 8 9 int n,q; 10 int s[100005][2],f[100005],sz[100005]; 11 bool rev[100005],rt[100005]; 12 ll v[100005],sum[100005],lza[100005],lzm[100005]; 13 14 void reverse(int p) 15 { 16 if(!p)return; 17 swap(s[p][0],s[p][1]); 18 rev[p]^=1; 19 } 20 21 void pushup(int p) 22 { 23 sz[p]=sz[s[p][0]]+sz[s[p][1]]+1; 24 sum[p]=(sum[s[p][0]]+sum[s[p][1]]+v[p])%M; 25 } 26 27 void mul(int p,ll c) 28 { 29 sum[p]=sum[p]*c%M; 30 v[p]=v[p]*c%M; 31 lzm[p]=lzm[p]*c%M; 32 lza[p]=lza[p]*c%M; 33 } 34 35 void plus(int p,ll c) 36 { 37 sum[p]=(sum[p]+sz[p]*c%M)%M; 38 v[p]=(v[p]+c)%M; 39 lza[p]=(lza[p]+c)%M; 40 } 41 42 void pushdown(int p) 43 { 44 if(lzm[p]!=1)mul(s[p][0],lzm[p]),mul(s[p][1],lzm[p]),lzm[p]=1; 45 if(lza[p])plus(s[p][0],lza[p]),plus(s[p][1],lza[p]),lza[p]=0; 46 if(rev[p])reverse(s[p][0]),reverse(s[p][1]),rev[p]=0; 47 } 48 49 void rotate(int p) 50 { 51 int k=id(p); 52 int fa=f[p]; 53 if(rt[fa])rt[p]=1,rt[fa]=0; 54 else s[f[fa]][id(fa)]=p; 55 s[fa][k]=s[p][!k]; 56 s[p][!k]=fa; 57 f[p]=f[fa]; 58 f[fa]=p; 59 f[s[fa][k]]=fa; 60 pushup(fa); 61 pushup(p); 62 } 63 64 void down(int p) 65 { 66 if(!rt[p])down(f[p]); 67 pushdown(p); 68 } 69 70 void splay(int p) 71 { 72 down(p); 73 while(!rt[p]) 74 { 75 int fa=f[p]; 76 if(rt[fa]) 77 { 78 rotate(p); 79 return; 80 } 81 if(id(p)^id(fa))rotate(p); 82 else rotate(fa); 83 rotate(p); 84 } 85 } 86 87 void access(int p) 88 { 89 int son=0; 90 while(p) 91 { 92 splay(p); 93 rt[s[p][1]]=1,rt[son]=0; 94 s[p][1]=son; 95 pushup(p); 96 son=p,p=f[p]; 97 } 98 } 99 100 void mtr(int p) 101 { 102 access(p); 103 splay(p); 104 reverse(p); 105 } 106 107 void link(int x,int y) 108 { 109 mtr(x); 110 f[x]=y; 111 } 112 113 void isolate(int x,int y) 114 { 115 mtr(x); 116 access(y); 117 splay(y); 118 } 119 120 int main() 121 { 122 scanf("%d%d",&n,&q); 123 for(int i=1;i<=n;i++)lzm[i]=sz[i]=v[i]=rt[i]=1; 124 for(int i=1;i<n;i++) 125 { 126 int x,y; 127 scanf("%d%d",&x,&y); 128 link(x,y); 129 } 130 while(q--) 131 { 132 char op[5]; 133 scanf("%s",op+1); 134 int pu,pv,nu,nv; 135 ll c; 136 if(op[1]=='+') 137 { 138 scanf("%d%d%lld",&pu,&pv,&c); 139 isolate(pu,pv); 140 plus(pv,c); 141 } 142 if(op[1]=='-') 143 { 144 scanf("%d%d%d%d",&pu,&pv,&nu,&nv); 145 isolate(pu,pv); 146 s[pv][0]=f[pu]=0; 147 rt[pu]=1; 148 link(nu,nv); 149 } 150 if(op[1]=='*') 151 { 152 scanf("%d%d%lld",&pu,&pv,&c); 153 isolate(pu,pv); 154 mul(pv,c); 155 } 156 if(op[1]=='/') 157 { 158 scanf("%d%d",&pu,&pv); 159 isolate(pu,pv); 160 printf("%lld\n",sum[pv]); 161 } 162 } 163 return 0; 164 }