Luogu3732 [HAOI2017] 供给侧改革 【后缀数组】【线段树】【乱搞】
题目分析:
这道题我是乱搞的,因为他说$01$串是随机的。
那么我们可以猜测能够让LCP变大的地方很少。求出后缀数组之后可能让LCP变大的地方就等价于从大到小往height里动态加点同时维护这个点左右两边的单调栈。
这个事情用线段树模拟就行了。
用暴力跑一下发现果然不大,只有200w,其中很多还是废点,把废点特判一下删除掉就行了。
然后把询问离线,按r排序,再作扫描线,每次扫到r的时候把前面变动的LCP更新一下。然后对于询问也做一个类似上面单调栈的操作。
代码:
1 #include<bits/stdc++.h> 2 #define RI register 3 using namespace std; 4 5 const int maxn = 100020; 6 const int N = 100000; 7 8 int n,q; 9 char str[maxn]; 10 int T[maxn<<2],a[maxn]; 11 int RMQ[maxn][19],pw[maxn]; 12 13 struct node{int l,r,nb;}qy[maxn]; 14 int ans[maxn]; 15 int sa[maxn],rk[maxn],X[maxn],Y[maxn]; 16 int ht[maxn],h[maxn]; 17 18 void fstread(int &x){ 19 char ch = getchar();x = 0; 20 while(ch > '9' || ch < '0') ch = getchar(); 21 while(ch >= '0' && ch <= '9') x = x*10+ch-'0',ch=getchar(); 22 } 23 24 int chk(int x,int k){ 25 return rk[sa[x]]==rk[sa[x-1]]&&rk[sa[x]+(1<<k)]==rk[sa[x-1]+(1<<k)]; 26 } 27 28 void GetSA(){ 29 for(RI int i=0;i<n;i++) X[str[i]]++; 30 for(RI int i=1;i<=N;i++) X[i] += X[i-1]; 31 for(RI int i=n-1;i>=0;i--) sa[X[str[i]]--] = i; 32 for(RI int i = 2, num = 1;i <= n;i++) 33 rk[sa[i]] = (str[sa[i]] == str[sa[i-1]]?num:++num); 34 rk[sa[1]] = 1; 35 for(int k=1;(1<<k-1)<=n;k++){ 36 for(RI int i=1;i<=N;i++) X[i] = 0; 37 for(RI int i=n-(1<<k-1);i<n;i++) Y[i-n+(1<<k-1)+1]=i; 38 for(RI int i=1,j=(1<<k-1)+1;i<=n;i++) 39 if(sa[i]>=(1<<k-1))Y[j++]=sa[i]-(1<<k-1); 40 for(RI int i=0;i<n;i++) X[rk[i]]++; 41 for(RI int i=1;i<=N;i++) X[i]+=X[i-1]; 42 for(RI int i=n;i>=1;i--) sa[X[rk[Y[i]]]--] = Y[i]; 43 int num = 1; Y[sa[1]] = 1; 44 for(RI int i=2;i<=n;i++) Y[sa[i]] = (chk(i,k-1)?num:++num); 45 for(RI int i=0;i<n;i++) rk[i] = Y[i]; 46 if(num == n) break; 47 } 48 } 49 50 void buildRMQ(){ 51 for(int i=1;i<=n;i++) RMQ[i][0] = ht[i]; 52 for(int i=0;(1<<i)<=n;i++) pw[(1<<i)] = i; 53 for(int i=3;i<=n;i++) if(!pw[i]) pw[i] = pw[i-1]; 54 for(int k=1;(1<<k)<=n;k++){ 55 for(RI int i=1;i<=n;i++){ 56 if(i+(1<<k-1)>n) RMQ[i][k] = RMQ[i][k-1]; 57 else RMQ[i][k] = min(RMQ[i][k-1],RMQ[i+(1<<k-1)][k-1]); 58 } 59 } 60 } 61 62 void GetHeight(){ 63 for(RI int i=0;i<n;i++){ 64 if(i) h[i] = max(0,h[i-1]-1); 65 if(rk[i] == 1) {h[i] = 0;continue;} 66 while(str[i+h[i]] == str[sa[rk[i]-1]+h[i]]) h[i]++; 67 } 68 for(RI int i=0;i<n;i++) ht[rk[i]] = h[i]; 69 } 70 71 int LCP(int l,int r){ 72 l = rk[l],r = rk[r]; if(l > r) swap(l,r);l++; 73 int k = pw[r-l+1]; 74 return min(RMQ[l][k],RMQ[r-(1<<k)+1][k]); 75 } 76 77 void update(int now,int tl,int tr,int pos,int len){ 78 if(tl == tr){T[now] = max(T[now],len); return;} 79 int mid = (tl+tr)/2; 80 if(pos <= mid) update(now<<1,tl,mid,pos,len); 81 else update(now<<1|1,mid+1,tr,pos,len); 82 T[now] = max(T[now<<1],T[now<<1|1]); 83 } 84 85 int Query(int now,int tl,int tr,int l,int r,int mx){ 86 if(tl >= l && tr <= r){ 87 if(T[now] <= mx) return -1; 88 else{ 89 while(tl < tr){ 90 int mid = (tl+tr)/2; 91 if(T[now<<1|1] > mx) tl = mid+1,now = now*2+1; 92 else tr = mid,now<<=1; 93 } 94 return tl; 95 } 96 } 97 if(tl > r || tr < l) return -1; 98 int mid = (tl+tr)/2; 99 if(mid >= r) return Query(now<<1,tl,mid,l,r,mx); 100 if(mid < l) return Query(now<<1|1,mid+1,tr,l,r,mx); 101 int z = Query(now<<1|1,mid+1,tr,l,r,mx); 102 if(z!=-1) return z; 103 else return Query(now<<1,tl,mid,l,r,mx); 104 } 105 106 vector<int> mlgb[maxn]; 107 108 namespace BruteForce{ 109 int minn[maxn<<2]; 110 111 pair<int,int> QueryRange(int now,int tl,int tr,int l,int r,int up,int d){ 112 if(tl >= l && tr <= r && d == 1){ 113 if(minn[now] < up){ 114 while(tl != tr){ 115 int mid = (tl+tr)/2; 116 if(minn[now<<1|1] < up) tl = mid+1,now=now*2+1; 117 else tr = mid,now<<=1; 118 } 119 return make_pair(minn[now],tl); 120 }else return make_pair(0,0); 121 } 122 if(tl >= l && tr <= r && d == 0){ 123 if(minn[now] < up){ 124 while(tl != tr){ 125 int mid = (tl+tr)/2; 126 if(minn[now<<1] < up) tr = mid,now<<=1; 127 else tl = mid+1,now=now*2+1; 128 } 129 return make_pair(minn[now],tl); 130 }else return make_pair(0,0); 131 } 132 if(tl > r || tr < l) return make_pair(0,0); 133 int mid = (tl+tr)/2; 134 if(mid>=r) return QueryRange(now<<1,tl,mid,l,r,up,d); 135 if(mid<l) return QueryRange(now<<1|1,mid+1,tr,l,r,up,d); 136 if(d){ 137 pair<int,int> z = QueryRange(now<<1|1,mid+1,tr,l,r,up,d); 138 if(z.first) return z; 139 else return QueryRange(now<<1,tl,mid,l,r,up,d); 140 }else{ 141 pair<int,int> z = QueryRange(now<<1,tl,mid,l,r,up,d); 142 if(z.first) return z; 143 else return QueryRange(now<<1|1,mid+1,tr,l,r,up,d); 144 } 145 } 146 void add(int now,int tl,int tr,int pos,int dt){ 147 if(tl == tr) {minn[now] = dt;return;} 148 int mid = (tl+tr)/2; 149 if(pos <= mid) add(now<<1,tl,mid,pos,dt); 150 else add(now<<1|1,mid+1,tr,pos,dt); 151 minn[now] = min(minn[now<<1],minn[now<<1|1]); 152 } 153 154 void holyshit(){ 155 memset(minn,0x3f,sizeof(minn)); 156 for(int i=n-1;i>=0;i--){ 157 int z = rk[i],p=19260817; 158 add(1,1,n,z,i); 159 while(true){ 160 pair<int,int> um = QueryRange(1,1,n,z+1,n,p,0); 161 if(!um.first) break; 162 mlgb[um.first].push_back(i); 163 z = um.second; p = sa[z]; 164 } 165 z = rk[i],p = 19260817; 166 while(true){ 167 pair<int,int> um = QueryRange(1,1,n,1,z-1,p,1); 168 if(!um.first) break; 169 mlgb[um.first].push_back(i); 170 z = um.second; p = sa[z]; 171 } 172 } 173 174 } 175 } 176 177 void work(){ 178 GetSA(); 179 GetHeight(); 180 buildRMQ(); 181 182 BruteForce::holyshit(); 183 int num = 1; 184 for(int i=0;i<n;i++){ 185 for(int j=0;j<mlgb[i].size();j++){ 186 int z = LCP(mlgb[i][j],i); 187 if(a[mlgb[i][j]] >= z) continue; 188 a[mlgb[i][j]] = z; 189 update(1,0,n-1,mlgb[i][j],z); 190 191 } 192 while(qy[num].r == i){ 193 int z = 0,pq = qy[num].r-1; 194 while(pq >= qy[num].l){ 195 int hp = Query(1,0,n-1,0,pq,z); 196 if(hp < qy[num].l) hp = qy[num].l-1; 197 ans[qy[num].nb] += (pq-hp)*z; 198 if(hp < 0) break; 199 z = a[hp],pq = hp; 200 } 201 num++; 202 } 203 } 204 for(int i=1;i<=q;i++) printf("%d\n",ans[i]); 205 } 206 207 int cmp(node alpha,node beta){return alpha.r < beta.r;} 208 int main(){ 209 //freopen("1.in","r",stdin); 210 fstread(n);fstread(q); 211 for(int i=1;i<=n;i++){ 212 str[i-1] = getchar(); 213 while(str[i-1]!= '0' && str[i-1] != '1') str[i-1] = getchar(); 214 } 215 for(int i=1;i<=q;i++) fstread(qy[i].l),fstread(qy[i].r),qy[i].nb=i; 216 for(int i=1;i<=q;i++) qy[i].l--,qy[i].r--; 217 sort(qy+1,qy+q+1,cmp); 218 work(); 219 return 0; 220 }
转载于:https://www.cnblogs.com/Menhera/p/10555157.html
Luogu3732 [HAOI2017] 供给侧改革 【后缀数组】【线段树】【乱搞】相关推荐
- 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 ...
- 【 bzoj 4355 】 Play with sequence - 线段树乱搞
先讲个故事... 据说某一天,claris扔了一道题到某群里面然后引起了不大的讨论~然后好学向上的whx同学发现了这题...聪明的whx想了很久...然后!whx发现看不懂claris给的暴力的证明. ...
- 洛谷 P3732 [HAOI2017]供给侧改革【trie树】
参考:http://blog.csdn.net/di4covery/article/details/73065684 我以为是后缀数组+某某数据结构,结果居然是01trie!!题解说"因为是 ...
- CF-547E(Mike and Friends)后缀数组+线段树 AC自动机+DFS序+树状数组
题目链接 题意 NNN个串,每次询问区间[L,R][L,R][L,R]中有多少子串SiS_iSi 思路 把NNN个串合成一个长字符串,对这个长字符串求后缀数组,包含SiS_iSi的子串的heigh ...
- [HAOI2017]供给侧改革
先将询问离线,把询问按照r分类,从小到大回答每一个询问. 由随机的性质得知两个串的lcp不会特别长,我们令其最长为40 对于区间[1,R],[2,R],[3,R]-[R-1,R],求其中最长的LCP一 ...
- HDU 6194 string string string (后缀数组+线段树)
题目https://cn.vjudge.net/problem/HDU-6194 没想到怎么用height数组求个数,看了看题解结合自己写的才明白, 妙啊. 我们按照height数组的特点,heigh ...
- 供给侧改革与去产能对安防产业啥影响
2016年,在经济下行压力巨大,GDP预估增长继续下降的大环境下,中央经济工作会议提出了一系列经济改革措施,其中"供给侧改革与去产能"对各产业的影响尤为关键,优化经济发展结构,提高 ...
- 大数据可精细化推进“供给侧”改革
文:张涵诚 需要产业发展推荐引擎系统和中国产业信息平台 需求和供给的相对平衡是国民经济的平稳的决定性因素.要达到这个平衡,国家提出要供给侧改革.看过很多供给侧改革的文章,大部分比较宏观,而笔者认为精细 ...
- 德尔汝继勇:地板行业供给侧改革与企业转型升级
本次大会吸引了海内外地板行业共三百余位嘉宾莅临现场,主要针对时下热门的"供给侧改革"."互联网+"以及"绿色发展"等内容,进行高端互动.作为 ...
最新文章
- 这才是我想要的云盘工具
- 用界面读取图片并且保存图片的方法
- python怎么让游戏倒计时_Python如何让倒计时效果的在固定区域刷新
- vue传中文标点_vue项目引入第三方高德地图实现标点定位
- bat批量剪切命令_批处理剪切文件夹的dos指令怎么写
- K8S学习笔记之使用Fluent-bit将容器标准输入和输出的日志发送到Kafka
- 在VS中安装nuget离线包nupkg文件
- 新蒂下午茶体基本版SentyTEA-Basic
- 从美国人工智能年会看2017世界人工智能最新研究成果
- 正方形、长方形、立方体 之二
- javascript网站期末作品~html电影资讯博客网站模板(HTML+CSS+JavaScript)在线电影网页设计...
- 八岁时我弄丢长命锁,七年后他说保我长命无忧
- matlab弹奏旋律(发声)笔记
- 硬货来了!轻松掌握 MongDB 流式聚合操作
- 基于微信小程序房屋出租民宿预定app设计
- 物联网通信技术第9章 异构网络协同通信
- 《哈利·波特:霍格沃茨之谜》游戏特推出万圣节内容致敬黑魔法
- L1 操作系统的启动
- 强制推到远程git push
- 人工生命42(人工智能原创小说)
热门文章
- c 结构体 不允许使用不完整的类型_.NET Core 基础类型介绍
- android webview 截图,Android获取webView快照与屏幕截屏的方法 -电脑资料
- 什么是 restful api
- flask双向映射语法
- jsessionid
- 产品经理应该如何设计面包屑原理
- excel打印预览在哪里_Excel如何打印表格,每页纸都有标题?
- bat/cmd将命令执行的结果赋值给变量
- (转)fatal error C1853: precompiled header file is from a previous version of the compiler, or the pre
- 在控制台输入一个整数,根据整数打印一个矩形 (Python)