[洛谷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
",sum[pv]);
161         }
162     }
163     return 0;
164 }
原文地址:https://www.cnblogs.com/eternhope/p/9650983.html