题意:
给出一个的串 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相关推荐

  1. 【线段树 泰勒展开】Codechef April Challenge 2018 Chef at the Food Fair

    第一次写泰勒展开:本地和CC差距好大 题目大意 大厨住的城市里办了一场美食节.一条街上开设了$N$个摊位,编号为$1∼N$.这天开始时,第$i$个摊位的食物会导致食物中毒的概率是$P_i$.在这一天中 ...

  2. Codechef August Challenge 2018 : Coordinate Compression

    传送门 外边二分,里面拿线段树维护贪心就行了. #include<cstdio> #include<vector> #include<cstring> #inclu ...

  3. Codechef July Challenge 2018 : Subway Ride

    传送门 首先(想了很久之后)注意到一个性质:同一条边有多种颜色的话保留3种就可以了,这是因为假如最优解要求当前位置与相邻两条边都不相同,那么只要有3条边,就肯定可以满足这一点. 完事就做一个nlogn ...

  4. 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] 表示第 ...

  5. CodeChef March Lunchtime 2018 div2

    地址https://www.codechef.com/LTIME58B?order=desc&sortBy=successful_submissions 简单做了一下,前三题比较水,第四题应该 ...

  6. 2018 湘潭邀请赛 K.2018

    K. 2018 2018 的约数只有 4 个,可以算出区间内和 2018 的最⼤公约数是 1, 2, 1009, 2018 的各有⼏个,之后 4 × 4 枚举统计答案. #include <io ...

  7. codechef October Challenge 2017解题报告

    第二次打challenge..果然还是拿不到钱(艹不过大佬)啊. A Balanced Contest 模拟就好. #include <bits/stdc++.h> #define gc ...

  8. [题解]CodeChef APRIL Challenge 17

    Similar Dishes 题意简述 给你两个大小为 4 4的字符串集合,问你并集是不是空集. 数据范围 1≤T≤2001 \leq T \leq 200 2≤len≤10 2 \leq len \ ...

  9. 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 次询问,每次给出 ...

最新文章

  1. 【ACM】杭电OJ 2010
  2. 面向初学者的10个热门计算机视觉项目
  3. python下载教程3.7-Python3
  4. 【收藏】wsl2 出现 Vmmem内存占用过大问题解决
  5. Java临时缓存API –测试早期草案评审RI
  6. 【ES】ES 写入数据流程
  7. 两种include方式及filter中的dispatcher解析
  8. android java service_[Java教程]Android四大组件之Service浅见
  9. pilz pnoz s4说明书_pilz安全继电器PNOZ端子及接线功能描述(中英对照版)
  10. Java多线程系列--“JUC集合”05之 ConcurrentSkipListMap
  11. ECPC16-E. Jumping(bfs)
  12. 采访了 10 位身价过亿的 CEO,我终于看懂了有钱人的“奋斗”
  13. 我本一心向明月,奈何明月照沟渠。真是知我者谓我心忧,不知我者谓我何求啊。
  14. macbook proa1708_Macbook pro2017 a1708转接卡更换大容量硬盘
  15. JavaScript之“创意时钟”项目
  16. Vue实现导入Excel功能
  17. 日语 假名对应的汉字来源
  18. php 数组的结构和定义
  19. LintCode 1218. 补数 JavaScript算法
  20. python公司网站毕业设计开题报告

热门文章

  1. Exception和RuntimeException的区别
  2. 重新绑定ItemsSource先设置ItemsSource = null;的原因
  3. js中怎么写自执行函数
  4. ffmpeg文档08-表达式计算/求值
  5. SQL 快速入门2.1
  6. ZOJ Problem Set - 1067 Color Me Less
  7. Vue2的核心原理剖析
  8. 你对ES6究竟了解多少?—— 有这一篇就够用了
  9. vue --- 2.0 编译的实现
  10. spring cloud gateway的stripPrefix配置