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\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 后缀平衡树 线段树相关推荐
- 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 ...
- 【BZOJ4370】【IOI2015】horses 数据结构 平衡树+线段树
4370: [IOI2015]horses马 Time Limit: 30 Sec Memory Limit: 1500 MB Description 像他的祖先一样,Mansur喜欢繁殖马匹.目前, ...
- 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 2271 Solved: 935 [Submit][St ...
- CF-547E(Mike and Friends)后缀数组+线段树 AC自动机+DFS序+树状数组
题目链接 题意 NNN个串,每次询问区间[L,R][L,R][L,R]中有多少子串SiS_iSi 思路 把NNN个串合成一个长字符串,对这个长字符串求后缀数组,包含SiS_iSi的子串的heigh ...
- Codeforces.666E.Forensic Examination(广义后缀自动机 线段树合并)
题目链接 \(Description\) 给定串\(S\)和\(m\)个串\(T_i\).\(Q\)次询问,每次询问\(l,r,p_l,p_r\),求\(S[p_l\sim p_r]\)在\(T_l\ ...
- luoguP5108 仰望半月的夜空 [官方?]题解 后缀数组 / 后缀树 / 后缀自动机 + 线段树 / st表 + 二分...
仰望半月的夜空 题解 可以的话,支持一下原作吧... 这道题数据很弱..... 因此各种乱搞估计都是能过的.... 算法一 暴力长度然后判断判断,复杂度\(O(n^3)\) 期望得分15分 算法二 通 ...
- Codeforces.700E.Cool Slogans(后缀自动机 线段树合并 DP)
题目链接 \(Description\) 给定一个字符串\(s[1]\).一个字符串序列\(s[\ ]\)满足\(s[i]\)至少在\(s[i-1]\)中出现过两次(\(i\geq 2\)).求最大的 ...
- 【CF666E】Forensic Examination - 广义后缀自动机+线段树合并
广义SAM专题的最后一题了--呼 题意: 给出一个长度为$n$的串$S$和$m$个串$T_{1\cdots m}$,给出$q$个询问$l,r,pl,pr$,询问$S[pl\cdots pr]$在$T_ ...
- HDU 6194 string string string (后缀数组+线段树)
题目https://cn.vjudge.net/problem/HDU-6194 没想到怎么用height数组求个数,看了看题解结合自己写的才明白, 妙啊. 我们按照height数组的特点,heigh ...
最新文章
- hdu-1108 最小公倍数
- 第八课.EM算法的合理性与算法推导
- xp与Linux双系统共存
- ACM第一天研究懂的AC代码——BFS问题解答——习题zoj2165
- 用C#二次封装虹软arcface
- 【很详细】JDK安装与环境变量配置
- 求1+2+3+...+n的值。
- matlab cd参数,MATLAB变量参数列表​
- 矩阵论-线性变换的特征值与特征变换
- 10倍加速!爱奇艺超分辨模型加速实践
- python pandas判断是否为空
- 雷军,扎克伯格,Linus 等巨佬的办公桌
- 凸优化第三章凸函数 3.3共轭函数
- 字节跳动否认完成支付牌照收购,但金融野心一直有
- strstr函数的学习
- A-KAZE论文研读
- FOC之Clarke变换和Park变换
- 第29届奥林匹克运动会组织委员会介绍
- Dex.top“50计划”牵手IOST,赋能公链生态经济
- pscad 如何产生一个阶跃信号_pscad 如何产生一个阶跃信号_如何简单得到一个单光子源——基于自发参量下转换的预示单光子产生......
热门文章
- ReportViewer教程(11)-给报表特定的内容设置颜色
- oppoR17手机计算机的隐藏功能,OPPO R17 Pro隐藏了很多你不知道的黑科技,让你高效使用手机...
- python 面向对象编程tcp_python 闯关之路三(面向对象与网络编程)
- 吴恩达深度学习 —— 2.18(选修)逻辑回归损失函数的解释
- leetcode - 1143. 最长公共子序列
- configure、pkg-config、pkg_config_path三者的关系
- 2014年值得关注的10个开源项目 上
- 读《程序员修炼之道——从小工到专家》(The Pragmatic Programmer: From Journeyman to Master)
- SLAM - 01 - 分类
- 网页没有横向滚动条_【第四课】网页里的表单