Codechef January Challenge 2018 - Killjee and k-th letter
题意:
给出一个的串 s,将 s 所有子串按照字典序排列好相接起来形成一个新串q次询问,每一次询问问新串中的第 k 个字符是什么,强制在线。
$|s|,q \le 2*10^{5} $
跟所有子串有关,那肯定要么是后缀自动机,要么是后缀树。
考虑后缀自动机。即使后缀自动机单次询问可以做到线性,在这题也无施展之地。鉴于他DAWG的性质,没有什么东西可以维护。
然而后缀树就不一样了,[TJOI2015] 弦论有一种O(n+logn)的做法,可以参考Mangoyang的博客。
实际上考虑 parent 可以进一步优化算法的复杂度,考虑原先的 parent 树一个节点代表的多个串都是最长的串的一个后缀,是一棵类似于前缀树的结构,这样不能适用于一些字典序上优美的性质。不妨将串反序插入到sam 中,这样每一个点能代表的多个串都是最长的串的前缀,这些串从长到短在字典序上一定是有序的。扩展到整棵树上,根据 minlen(u)=len(fa(u))+1 ,每个点代表的字符串都比其祖先代表的字符串的字典序大。于是可以计算出每一棵子树代表了多少串,在 dfn 序上二分答案即可
类似的,也可以计算出后缀树每一颗子树代表的串的总长,并且通过构造可以使后缀树上字符串的字典序与 dfn 序同时有序。这样找到了后缀树上的一个节点后,考虑一个子串其所代表的串长度在 [len(fa(u))+1,len(u)] 上连续,在这个节点上继续二分答案就可以找到第k个字符所在的子串及它的长度,再计算一下就能知道第k个字符在s中的位置了。时间复杂度O(n+qlogn)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 int const N=200000+10; 5 struct node{ 6 int len,fa,ch[26]; 7 }a[N<<1]; 8 int tot,ls,w[N<<1],num[N],sa[N<<1],cnt,pos[N<<1],son[N<<1][26]; 9 ll sum[N<<1],l[N<<1],sz[N<<1],qs[N<<1]; 10 char s[N]; 11 void add(int c,int id){ 12 int p=ls; 13 int np=ls=++tot; 14 a[np].len=a[p].len+1; 15 w[tot]=id; 16 sz[tot]=1; 17 for(;p&&!a[p].ch[c];p=a[p].fa) a[p].ch[c]=np; 18 if(!p) a[np].fa=1; 19 else { 20 int q=a[p].ch[c]; 21 if(a[q].len==a[p].len+1) a[np].fa=q; 22 else { 23 int nq=++tot; 24 a[nq]=a[q]; 25 a[nq].len=a[p].len+1; 26 a[q].fa=a[np].fa=nq; 27 for(;p&&a[p].ch[c]==q;p=a[p].fa) 28 a[p].ch[c]=nq; 29 } 30 } 31 } 32 void dfs(int x){ 33 if(!x ) return ; 34 pos[++cnt]=x; 35 for(int i=0;i<26;i++) 36 dfs(son[x][i]); 37 } 38 int main(){ 39 scanf("%s",s); 40 int len=strlen(s); 41 tot=ls=1; 42 for(int i=len-1;i>=0;i--) 43 add(s[i]-'a',i+1); 44 for(int i=2;i<=tot;i++) 45 sum[i]=1; 46 for(int i=1;i<=tot;i++) num[a[i].len]++; 47 for(int i=1;i<=len;i++) num[i]+=num[i-1]; 48 for(int i=1;i<=tot;i++) sa[num[a[i].len]--]=i; 49 for(int i=tot;i>=1;i--){ 50 int x=sa[i]; 51 int f=a[x].fa; 52 sz[f]+=sz[x]; 53 w[f]=w[f ]? w[f]:w[x]; 54 } 55 for(int i=2;i<=tot;i++){ 56 int x=a[i].fa; 57 int y=s[w[i]+a[a[i].fa].len-1]-'a'; 58 son[x][y]=i; 59 } 60 dfs(1); 61 for(int i=2;i<=tot;i++) { 62 int t=pos[i]; 63 ll x=a[a[t].fa].len+1; 64 ll y=a[t].len; 65 ll tmp=sz[t]*(x+y)*(y-x+1)/2; 66 qs[i]=qs[i-1]+tmp; 67 } 68 69 int q; 70 scanf("%d",&q); 71 ll g=0; 72 while (q--){ 73 ll p,m; 74 scanf("%lld%lld",&p,&m); 75 ll k=p*g % m +1; 76 int t=lower_bound(qs+1,qs+tot+1,k)-qs; 77 k-=qs[t-1]; 78 t=pos[t]; 79 ll x=a[a[t].fa].len+1; 80 ll y=a[t].len; 81 ll tmp=sz[t]*(x+y)*(y-x+1)/2; 82 ll l=x,r=y; 83 while (l<r){ 84 ll mid=(l+r)/2; 85 tmp=sz[t]*(x+mid)*(mid-x+1)/2; 86 if(tmp>=k) r=mid; 87 else l=mid+1; 88 } 89 k-=sz[t]*(x+r-1)*(r-x)/2; 90 k=(k-1) % r+1; 91 int c=w[t]+k-2; 92 printf("%c\n",s[c]); 93 g+=s[c]; 94 } 95 return 0; 96 }
View Code
转载于:https://www.cnblogs.com/ZJXXCN/p/11054391.html
Codechef January Challenge 2018 - Killjee and k-th letter相关推荐
- 【线段树 泰勒展开】Codechef April Challenge 2018 Chef at the Food Fair
第一次写泰勒展开:本地和CC差距好大 题目大意 大厨住的城市里办了一场美食节.一条街上开设了$N$个摊位,编号为$1∼N$.这天开始时,第$i$个摊位的食物会导致食物中毒的概率是$P_i$.在这一天中 ...
- Codechef August Challenge 2018 : Coordinate Compression
传送门 外边二分,里面拿线段树维护贪心就行了. #include<cstdio> #include<vector> #include<cstring> #inclu ...
- Codechef July Challenge 2018 : Subway Ride
传送门 首先(想了很久之后)注意到一个性质:同一条边有多种颜色的话保留3种就可以了,这是因为假如最优解要求当前位置与相邻两条边都不相同,那么只要有3条边,就肯定可以满足这一点. 完事就做一个nlogn ...
- CFCC百套计划2 CodeChef December Challenge 2017 Chef And Easy Xor Queries
https://www.codechef.com/DEC17/problems/CHEFEXQ 题意: 位置i的数改为k 询问区间[1,i]内有多少个前缀的异或和为k 分块 sum[i][j] 表示第 ...
- CodeChef March Lunchtime 2018 div2
地址https://www.codechef.com/LTIME58B?order=desc&sortBy=successful_submissions 简单做了一下,前三题比较水,第四题应该 ...
- 2018 湘潭邀请赛 K.2018
K. 2018 2018 的约数只有 4 个,可以算出区间内和 2018 的最⼤公约数是 1, 2, 1009, 2018 的各有⼏个,之后 4 × 4 枚举统计答案. #include <io ...
- codechef October Challenge 2017解题报告
第二次打challenge..果然还是拿不到钱(艹不过大佬)啊. A Balanced Contest 模拟就好. #include <bits/stdc++.h> #define gc ...
- [题解]CodeChef APRIL Challenge 17
Similar Dishes 题意简述 给你两个大小为 4 4的字符串集合,问你并集是不是空集. 数据范围 1≤T≤2001 \leq T \leq 200 2≤len≤10 2 \leq len \ ...
- Codechef Coders’Legacy 2018 CLSUMG Sum of Primes
Description 设 f(x)f(x) 表示把 xx 拆分成两个质数之和的方案数. 例如 f(10)=2f(10)=2 , 因为 10=3+7=5+510=3+7=5+5 TT 次询问,每次给出 ...
最新文章
- 【ACM】杭电OJ 2010
- 面向初学者的10个热门计算机视觉项目
- python下载教程3.7-Python3
- 【收藏】wsl2 出现 Vmmem内存占用过大问题解决
- Java临时缓存API –测试早期草案评审RI
- 【ES】ES 写入数据流程
- 两种include方式及filter中的dispatcher解析
- android java service_[Java教程]Android四大组件之Service浅见
- pilz pnoz s4说明书_pilz安全继电器PNOZ端子及接线功能描述(中英对照版)
- Java多线程系列--“JUC集合”05之 ConcurrentSkipListMap
- ECPC16-E. Jumping(bfs)
- 采访了 10 位身价过亿的 CEO,我终于看懂了有钱人的“奋斗”
- 我本一心向明月,奈何明月照沟渠。真是知我者谓我心忧,不知我者谓我何求啊。
- macbook proa1708_Macbook pro2017 a1708转接卡更换大容量硬盘
- JavaScript之“创意时钟”项目
- Vue实现导入Excel功能
- 日语 假名对应的汉字来源
- php 数组的结构和定义
- LintCode 1218. 补数 JavaScript算法
- python公司网站毕业设计开题报告