• 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

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

  • 相关阅读:
    初识Java,关于一个简单的ATM机的java程序设计
    字符串和字符串对象的区别
    集中常见得字符串处理方式
    得到类模板的3种方式
    反射的条件
    封装一个标签加文本框
    建立及中常见的布局管理器
    随机输入3个正整数,程序出来从小到大排列
    java 基础
    IO
  • 原文地址:https://www.cnblogs.com/Achenchen/p/8989771.html
Copyright © 2020-2023  润新知