*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;
}
posted @ 2022-08-03 16:17  Vijurria  阅读(57)  评论(0编辑  收藏  举报