国际惯例的题面:

考虑如果没有强制在线我们能怎么水掉这个题,先构造出字符串,各种方法求一下后缀数组,然后线段树维护区间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\n",lastans=sgt.query(1,1,n,l,r));
132     }
133     return 0;
134 }

View Code

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

转载于:https://www.cnblogs.com/Cmd2001/p/9016615.html

3682: Phorni 后缀平衡树 线段树相关推荐

  1. HDU 6194 String String String (后缀数组+线段树, 2017 ACM/ICPC Asia Regional Shenyang Online)

    Problem 求字符串 S 中严格出现 k 次的子串个数 k≥1k\ge 1 |S|≤105|S|\le 10^5 ∑|S|≤2×106\sum |S| \le 2\times 10^6 Idea ...

  2. 【BZOJ4370】【IOI2015】horses 数据结构 平衡树+线段树

    4370: [IOI2015]horses马 Time Limit: 30 Sec Memory Limit: 1500 MB Description 像他的祖先一样,Mansur喜欢繁殖马匹.目前, ...

  3. 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 2271  Solved: 935 [Submit][St ...

  4. CF-547E(Mike and Friends)后缀数组+线段树 AC自动机+DFS序+树状数组

    题目链接 题意 NNN个串,每次询问区间[L,R][L,R][L,R]中有多少子串SiS_iSi​ 思路 把NNN个串合成一个长字符串,对这个长字符串求后缀数组,包含SiS_iSi​的子串的heigh ...

  5. Codeforces.666E.Forensic Examination(广义后缀自动机 线段树合并)

    题目链接 \(Description\) 给定串\(S\)和\(m\)个串\(T_i\).\(Q\)次询问,每次询问\(l,r,p_l,p_r\),求\(S[p_l\sim p_r]\)在\(T_l\ ...

  6. luoguP5108 仰望半月的夜空 [官方?]题解 后缀数组 / 后缀树 / 后缀自动机 + 线段树 / st表 + 二分...

    仰望半月的夜空 题解 可以的话,支持一下原作吧... 这道题数据很弱..... 因此各种乱搞估计都是能过的.... 算法一 暴力长度然后判断判断,复杂度\(O(n^3)\) 期望得分15分 算法二 通 ...

  7. Codeforces.700E.Cool Slogans(后缀自动机 线段树合并 DP)

    题目链接 \(Description\) 给定一个字符串\(s[1]\).一个字符串序列\(s[\ ]\)满足\(s[i]\)至少在\(s[i-1]\)中出现过两次(\(i\geq 2\)).求最大的 ...

  8. 【CF666E】Forensic Examination - 广义后缀自动机+线段树合并

    广义SAM专题的最后一题了--呼 题意: 给出一个长度为$n$的串$S$和$m$个串$T_{1\cdots m}$,给出$q$个询问$l,r,pl,pr$,询问$S[pl\cdots pr]$在$T_ ...

  9. HDU 6194 string string string (后缀数组+线段树)

    题目https://cn.vjudge.net/problem/HDU-6194 没想到怎么用height数组求个数,看了看题解结合自己写的才明白, 妙啊. 我们按照height数组的特点,heigh ...

最新文章

  1. hdu-1108 最小公倍数
  2. 第八课.EM算法的合理性与算法推导
  3. xp与Linux双系统共存
  4. ACM第一天研究懂的AC代码——BFS问题解答——习题zoj2165
  5. 用C#二次封装虹软arcface
  6. 【很详细】JDK安装与环境变量配置
  7. 求1+2+3+...+n的值。
  8. matlab cd参数,MATLAB变量参数列表​
  9. 矩阵论-线性变换的特征值与特征变换
  10. 10倍加速!爱奇艺超分辨模型加速实践
  11. python pandas判断是否为空
  12. 雷军,扎克伯格,Linus 等巨佬的办公桌
  13. 凸优化第三章凸函数 3.3共轭函数
  14. 字节跳动否认完成支付牌照收购,但金融野心一直有
  15. strstr函数的学习
  16. A-KAZE论文研读
  17. FOC之Clarke变换和Park变换
  18. 第29届奥林匹克运动会组织委员会介绍
  19. Dex.top“50计划”牵手IOST,赋能公链生态经济
  20. pscad 如何产生一个阶跃信号_pscad 如何产生一个阶跃信号_如何简单得到一个单光子源——基于自发参量下转换的预示单光子产生......

热门文章

  1. ReportViewer教程(11)-给报表特定的内容设置颜色
  2. oppoR17手机计算机的隐藏功能,OPPO R17 Pro隐藏了很多你不知道的黑科技,让你高效使用手机...
  3. python 面向对象编程tcp_python 闯关之路三(面向对象与网络编程)
  4. 吴恩达深度学习 —— 2.18(选修)逻辑回归损失函数的解释
  5. leetcode - 1143. 最长公共子序列
  6. configure、pkg-config、pkg_config_path三者的关系
  7. 2014年值得关注的10个开源项目 上
  8. 读《程序员修炼之道——从小工到专家》(The Pragmatic Programmer: From Journeyman to Master)
  9. SLAM - 01 - 分类
  10. 网页没有横向滚动条_【第四课】网页里的表单