• 3682: Phorni 后缀平衡树 线段树


    国际惯例的题面:


    考虑如果没有强制在线我们能怎么水掉这个题,先构造出字符串,各种方法求一下后缀数组,然后线段树维护区间rank最小的位置即可。
    然而他要求强制在线,支持插入后缀,并比较后缀大小(求rank)的数据结构,当然就是后缀平衡树啦。
    于是插入字符串的操作,我们只需要在后缀平衡树上插入这个后缀。此时不需要对线段树进行修改,因为线段树中任何一个位置均不包含新插入的这个后缀(保证信息合法)。
    什么你说插入会改变每个后缀的rank值?没关系我们不需要知道每个后缀的rank具体是多少,我们只需要它们的相对大小关系,这个显然是不会改变的是吧。
    (你还不明白?先去A了"Bzoj3600: 没有人的算术"再说。什么你A了还不明白?丢人!褪裙吧!)
    然后对线段树的修改和查询就显然了。
    (话说这题treap不旋比旋转快,替罪羊alpha设为1最快,某大佬裸BST直接AC都是什么鬼啊)

    代码:

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cctype>
      4 const int maxe=1e6+1e2;
      5 const double alpha = 0.85;
      6 
      7 char in[maxe];
      8 int at[maxe]; // suffix i's node .
      9 double v[maxe];
     10 
     11 struct SuffixBalancedTree { // we should insert 0 as the minimal suffix .
     12     int lson[maxe],rson[maxe],siz[maxe],sf[maxe],root,cnt;
     13     int seq[maxe],sql;
     14     int fail,failfa;
     15     double vfl,vfr;
     16     
     17     inline bool cmp(int x,int y) {
     18         if( !x || !y ) return !x;
     19         if( in[x] != in[y] ) return in[x] < in[y];
     20         else return v[at[x-1]] < v[at[y-1]];
     21     }
     22     inline void upgrade(int pos,double l,double r) {
     23         siz[pos] = siz[lson[pos]] + siz[rson[pos]] + 1;
     24         if( std::max( siz[lson[pos]] , siz[rson[pos]] ) > siz[pos] * alpha ) fail = pos , failfa = -1 , vfl = l , vfr = r;
     25         else if( fail == lson[pos] || fail == rson[pos] ) failfa = pos;
     26     }
     27     inline void insert(int &pos,double l,double r,const int &id) {
     28         if( !pos ) {
     29             v[at[id]=pos=++cnt]= ( l + r ) / 2.0 , siz[pos] = 1 , sf[pos] = id;
     30             return;
     31         } const double vmid = ( l + r ) / 2.0;
     32         if( cmp(sf[pos],id) ) insert(rson[pos],vmid,r,id) , upgrade(pos,l,r); // id > sf[pos] .
     33         else insert(lson[pos],l,vmid,id) , upgrade(pos,l,r);
     34     }
     35     inline int rebuild(int ll,int rr,double l,double r) {
     36         const int mid = ( ll + rr ) >> 1 , pos = seq[mid];
     37         const double vmid = ( l + r ) / 2.0; v[pos] = vmid , siz[pos] = rr - ll + 1;
     38         if( ll < mid ) lson[pos] = rebuild(ll,mid-1,l,vmid);
     39         if( mid < rr ) rson[pos] = rebuild(mid+1,rr,vmid,r);
     40         return pos;
     41     }
     42     inline void dfs(int pos) {
     43         if(lson[pos]) dfs(lson[pos]);
     44         seq[++sql] = pos;
     45         if(rson[pos]) dfs(rson[pos]);
     46         lson[pos] = rson[pos] = siz[pos] = 0;
     47     }
     48     inline void insert(const int &id) {
     49         fail = 0 , failfa = -1 , insert(root,0,1,id);
     50         if(fail) {
     51             sql = 0 , dfs(fail);
     52             if( ~failfa ) {
     53                 if( fail == lson[failfa] ) lson[failfa] = rebuild(1,sql,vfl,vfr);
     54                 else rson[failfa] = rebuild(1,sql,vfl,vfr);
     55             } else root = rebuild(1,sql,0,1);
     56         }
     57     }
     58 }sbt;
     59 
     60 int cov[maxe>>1];
     61 
     62 struct SegmentTree {
     63     int mx[maxe<<1];
     64     #define lson(pos) (pos<<1)
     65     #define rson(pos) (pos<<1|1)
     66     inline bool cmp(int a,int b) {
     67         if( cov[a] == cov[b] ) return a < b;
     68         return v[at[cov[a]]] < v[at[cov[b]]];
     69     }
     70     inline void upgrade(int pos) {
     71         mx[pos] = cmp(mx[lson(pos)],mx[rson(pos)]) ? mx[lson(pos)] : mx[rson(pos)];
     72     }
     73     inline void build(int pos,int l,int r) {
     74         if( l == r ) return void( mx[pos] = l );
     75         const int mid = ( l + r ) >> 1;
     76         build(lson(pos),l,mid) , build(rson(pos),mid+1,r) , upgrade(pos);
     77     }
     78     inline void update(int pos,int l,int r,const int &tar) {
     79         if( l == r ) return; // nothing to update .
     80         const int mid = ( l + r ) >> 1;
     81         if( tar <= mid ) update(lson(pos),l,mid,tar);
     82         else update(rson(pos),mid+1,r,tar);
     83         upgrade(pos);
     84     }
     85     inline int query(int pos,int l,int r,const int &ll,const int &rr) {
     86         if( ll <= l && r <= rr ) return mx[pos];
     87         const int mid = ( l + r ) >> 1;
     88         if( rr <= mid ) return query(lson(pos),l,mid,ll,rr);
     89         else if( ll > mid ) return query(rson(pos),mid+1,r,ll,rr);
     90         const int ql = query(lson(pos),l,mid,ll,rr) , qr = query(rson(pos),mid+1,r,ll,rr);
     91         return cmp(ql,qr) ? ql : qr;
     92     }
     93 }sgt;
     94 
     95 inline char nextchar() {
     96     static const int BS = 1 << 21;
     97     static char buf[BS],*st=buf+BS,*ed=st;
     98     if( st == ed ) ed = buf + fread(st=buf,1,BS,stdin);
     99     return st == ed ? -1 : *st++;
    100 }
    101 inline void getstr(char* s) {
    102     char c;
    103     while( !isalpha(c=nextchar()) );
    104     do *s++=c; while( isalpha(c=nextchar()) );
    105 }
    106 inline char realchar() {
    107     char c;
    108     while( !isalpha(c=nextchar()) );
    109     return c;
    110 }
    111 inline int getint() {
    112     int ret = 0 , ch;
    113     while( !isdigit(ch=nextchar()) );
    114     do ret=ret*10+ch-'0'; while( isdigit(ch=nextchar()) );
    115     return ret;
    116 }
    117 
    118 int main() {
    119     static int n,m,len,tpe,lastans;
    120     n = getint() , m = getint() , len = getint() , tpe = getint() , getstr(in+1) , std::reverse(in+1,in+1+len);
    121     for(int i=0;i<=len;i++) in[i] -= 'a' , sbt.insert(i);
    122     for(int i=1;i<=n;i++) cov[i] = getint();
    123     sgt.build(1,1,n);
    124     for(int i=1,o,c,x,l,r;i<=m;i++) {
    125         o = realchar();
    126         if( o == 'I' ) {
    127             c = getint();
    128             if( tpe ) c ^= lastans;
    129             in[++len] = c , sbt.insert(len);
    130         } else if( o == 'C' ) x = getint() , cov[x] = getint() , sgt.update(1,1,n,x);
    131         else if( o == 'Q' ) l = getint() , r = getint() , printf("%d
    ",lastans=sgt.query(1,1,n,l,r));
    132     }
    133     return 0;
    134 }
    View Code



    思い出して 優しいハウリング
    回忆起 温柔的振鸣
    奏でる声 未来を示してた
    演奏之声 昭示了未来
    思い出して 優しいハウリング
    回忆起 温柔的共鸣
    遅くはない そう教えてくれた
    永远不会太迟 你是这样教我的
    今までの過ちすべて
    至今经历的一切
    巻き戻すことなんて出来はしない
    已不能倒带
    間違いを認める勇気
    不懂得承认错误的勇气
    知らなかったよ 凄く不器用に 生きてた
    十分笨拙的生存着

  • 相关阅读:
    [水煮 ASP.NET Web API2 方法论](3-6)万能路由
    [水煮 ASP.NET Web API2 方法论](3-5)路由约束
    [水煮 ASP.NET Web API2 方法论](3-4)设置路由可选项
    [水煮 ASP.NET Web API2 方法论](3-3)路由默认值
    [水煮 ASP.NET Web API2 方法论](3-2)直接式路由/属性路由
    [转载自简书] ASPNetCore上传大文件碰到的一些问题总结
    [转载] 关于web.config
    [转载] sessionState 4种mode模式
    [转载] web.config 配置详解
    文档注释标记
  • 原文地址:https://www.cnblogs.com/Cmd2001/p/9016615.html
Copyright © 2020-2023  润新知