*Codeforces Round #807 (Div. 2) C - Mark and His Unfinished Essay(字符串+预处理)
https://codeforces.com/contest/1705/problem/C
一天晚上,马克意识到明天有一篇论文要交。他还没有写任何东西,所以马克决定从提示中随机复制粘贴子字符串来写文章。
更正式地说,提示是一个初始长度为n的字符串Mark将执行c次复制粘贴操作。每个操作都用两个整数l和r来描述,也就是说Mark会在字符串s的末尾追加字母slsl+1…sr,
注意这个操作之后s的长度增加了。
当然,马克需要能够看到写了什么。复制后,Mark会问q个查询:给定一个整数k,确定最后一个字符串s的第k个字母。
保证所有测试用例的n和q之和分别不超过2⋅10^5和10^4。
input
2
4 3 3
mark
1 4
5 7
3 8
1
10
12
7 3 3
creamii
2 3
3 4
2 9
9
11
12
output
m
a
r
e
a
r
- 盲目把字符串往后边填充必定不是超时就是爆内存
从后往前映射,不断往前查找
最终还是能找到原字符所在的位置
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=500500;
const int M=2002;
LL sum[N],l[N],r[N];
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
int T=1;
cin>>T;
while(T--)
{
//长度为n,具有c次增加长度的次数,q次询问
LL n,c,q;
cin>>n>>c>>q;
//字符串s
string s;
cin>>s;
s=" "+s;
sum[0]=n;
for(int i=1;i<=c;i++)
{
cin>>l[i]>>r[i];
sum[i]=sum[i-1]+(r[i]-l[i]+1);//进行预处理,括号内的是l到r的长度
//cout<<sum[i]<<" ";
}
//cout<<endl;
while(q--)
{
LL x;
cin>>x;
for(int i=c;i>=1;i--)
{
//一直变小,把它从过长的长度转变成给定的字符串的长度
if(x>sum[i-1]&&x<=sum[i])
{
x-=(sum[i]-r[i]);
}
//cout<<x<<" ";
}
cout<<s[x]<<endl;
}
}
return 0;
}