2759: 一个动态树好题

传送门

发现当存在一个环,就可以求出环所在联通块上所有点的答案.

既然题目都告诉我是lct了,就想着搞一搞,

用splay维护每个点对根的方程,即splay维护这颗splay中深度最深的节点对于深度最浅节点的方程

然后脑子木的以为有很多非树边,在哪里各种乱搞,,各种暴力枚举想水一水...

我大概是个智障.

正解:

边是有向的,i->p[i]

有脑子的人都会知道这是一颗基环内向树

基环树有个套路就是不需要换根操作,把环上一条边拆了,其中一个点看做根,另一个点看做根的special_father

那么就很好做了,splay像上面那样维护.

link的时候如果没联通就直接link,否则只是把i的special_father设为p[i]

cut的时候如果是cut掉special_father.直接把special_father设为0

否则先cut成两个联通块,然后找到开始的根,若根的special_father重新联通这两个联通块就把这条边变成正常的树边,link起来,special_father设为0

查询的时候,access根的special_father即可算出根的答案,再access要查询的点即可

  1 //Achen
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<cstdio>
  7 #include<cmath>
  8 #include<queue>
  9 #include<set>
 10 #include<map>
 11 #define For(i,a,b) for(int i=(a);i<=(b);i++)
 12 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
 13 const int N=30000+7,P=10007;
 14 typedef long long LL;
 15 typedef double db;
 16 using namespace std;
 17 int n,Q,inv[P+7];
 18 char o[10];
 19 
 20 template<typename T>void read(T &x) {
 21     char ch=getchar(); x=0; T f=1;
 22     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
 23     if(ch=='-') f=-1,ch=getchar();
 24     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
 25 }
 26 
 27 int ch[N][2],p[N],sp[N],pp[N];
 28 #define lc ch[x][0]
 29 #define rc ch[x][1]
 30 struct data {
 31     int k,b;
 32     data(){ k=1; b=0; }
 33     data(int k,int b):k(k),b(b){}
 34     friend data operator *(const data&A,const data&B) {
 35         return data(A.k*B.k%P,(A.b*B.k%P+B.b)%P);
 36     }
 37 }sum[N],dt[N];
 38 
 39 int isroot(int x) { return (ch[p[x]][0]!=x&&ch[p[x]][1]!=x); }
 40 
 41 void update(int x) { sum[x]=sum[lc]*dt[x]*sum[rc]; }
 42 
 43 void rotate(int x) {
 44     int y=p[x],z=p[y],l=(x==ch[y][1]),r=l^1;
 45     if(!isroot(y)) ch[z][y==ch[z][1]]=x; p[x]=z;
 46     ch[y][l]=ch[x][r]; p[ch[x][r]]=y;
 47     ch[x][r]=y; p[y]=x;
 48     update(y); update(x);
 49 } 
 50 
 51 void splay(int x) {
 52     for(;!isroot(x);rotate(x)) {
 53         int y=p[x],z=p[y];
 54         if(!isroot(y)) 
 55             ((x==ch[y][1])^(y==ch[z][1]))?rotate(x):rotate(y);
 56     }
 57 }
 58 
 59 void access(int x) {
 60     for(int t=0;x;x=p[t=x]) {
 61         splay(x);
 62         rc=t;
 63         update(x);    
 64     }
 65 }
 66 
 67 int find_root(int x) {
 68     access(x);
 69     splay(x);
 70     while(lc) x=lc;
 71     return x;
 72 }
 73 
 74 void lik(int x,int y) {
 75     if(find_root(x)==find_root(y)) {
 76         sp[x]=y; return;
 77     }
 78     splay(x);
 79     p[x]=y;
 80 }
 81 
 82 void cut(int x,int y) {
 83     if(sp[x]==y) {
 84         sp[x]=0; return;
 85     }
 86     int z=find_root(x);
 87     lc=p[lc]=0; 
 88     update(x);
 89     if(sp[z]&&find_root(sp[z])!=find_root(z)) {
 90          access(z); 
 91          splay(z);
 92          p[z]=sp[z]; 
 93          sp[z]=0;
 94     }
 95 }
 96 
 97 void exgcd(int a,int b,int &x,int &y) {
 98     if(!b) { x=1; y=0; return; }
 99     exgcd(b,a%b,y,x); y-=a/b*x;
100 }
101 
102 void qry(int x) {
103     int y=find_root(x);
104     if(!sp[y]) puts("-2");
105     else {
106         access(sp[y]);
107         splay(sp[y]);
108         data tp=sum[sp[y]];
109         if(tp.k&&(!tp.b)) { puts("-1"); return; }
110         int a=(1-tp.k+P)%P;
111         int rs=!tp.k?tp.b:inv[a]*tp.b%P;
112         access(x);
113         splay(x);
114         rs=(sum[x].k*rs%P+sum[x].b)%P;
115         printf("%d
",rs);
116     }
117 }
118  
119 //#define DEBUG
120 int main() {
121 #ifdef DEBUG
122     freopen("1.in","r",stdin);
123     //freopen("1.out","w",stdout);
124 #endif
125     read(n);
126     inv[0]=inv[1]=1;
127     For(i,2,P) inv[i]=(P-P/i*inv[P%i]%P)%P;
128        For(i,1,n) {
129            read(dt[i].k); read(pp[i]); read(dt[i].b);
130            lik(i,pp[i]);
131        }
132        read(Q);
133        while(Q--) {
134            scanf("%s",o);
135            if(o[0]=='A') {
136                int xx; 
137                read(xx);
138                qry(xx);
139            }
140            else {
141                int xx,kk,ppp,bb;
142                read(xx); read(kk); read(ppp); read(bb);
143                cut(xx,pp[xx]);
144                splay(xx);
145                dt[xx].k=kk; dt[xx].b=bb;
146                update(xx);
147                pp[xx]=ppp;
148                lik(xx,pp[xx]);
149            }
150        }
151     return 0;
152 }
View Code

我真的好菜呀,,什么"经典模型","套路","众所周知的" 都不知道,什么"大水题","送分题","普及-的题"都做不来...

原文地址:https://www.cnblogs.com/Achenchen/p/8989771.html