cf_159C. String Manipulation线段树+字符串

C. String Manipulation 1.0
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

One popular website developed an unusual username editing procedure. One can change the username only by deleting some characters from it: to change the current name s, a user can pick number p and character c and delete the p-th occurrence of characterc from the name. After the user changed his name, he can't undo the change.

For example, one can change name "arca" by removing the second occurrence of character "a" to get "arc".

Polycarpus learned that some user initially registered under nickname t, where t is a concatenation of k copies of string s. Also, Polycarpus knows the sequence of this user's name changes. Help Polycarpus figure out the user's final name.

Input

The first line contains an integer k (1 ≤ k ≤ 2000). The second line contains a non-empty string s, consisting of lowercase Latin letters, at most 100 characters long. The third line contains an integer n (0 ≤ n ≤ 20000) — the number of username changes. Each of the next n lines contains the actual changes, one per line. The changes are written as "pi ci" (without the quotes), where pi (1 ≤ pi ≤ 200000) is the number of occurrences of letter cici is a lowercase Latin letter. It is guaranteed that the operations are correct, that is, the letter to be deleted always exists, and after all operations not all letters are deleted from the name. The letters' occurrences are numbered starting from 1.

Output

Print a single string — the user's final name after all changes are applied to it.

Sample test(s)
input
2
bac
3
2 a
1 b
2 c
output
acb
input
1
abacaba
4
1 a
1 a
1 c
2 b
output
baa
Note

Let's consider the first sample. Initially we have name "bacbac"; the first operation transforms it into "bacbc", the second one — to "acbc", and finally, the third one transforms it into "acb".

此题主要思路是:把每个字母的个数和出现位置以线段树的形式存储。

每个字母(共有26个)分别代表一个线段树,线段树的根结点保存该字母总共出现的次数,叶结点(l == r )保存字符出现的位置,每个“字符”线段树共同组成总的线段树,保存的是字符串的信息。

线段树本身用于大量元素的存储以及点或区间的修改(增加/赋值/删除),本题要求删除某个字符的第i次出现,正好可利用线段树解决。


</pre><pre name="code" class="cpp">#include <string.h>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define inf -0x3f3f3f3f
#define mem0(a) memset(a,0,sizeof(a))
#define maxn 200000+10
char s[maxn];
int vis[maxn];
int a[26][maxn<<2];
void Getsum(int ch,int cur){
    a[ch][cur]=a[ch][cur<<1]+a[ch][cur<<1|1];
}
void update(int ch,int i,int l,int r,int cur){//这里i代表编号位置,第i个字母
    if( l == r){
        a[ch][cur]=1;
        return ;
    }
    int mid = ( l + r)>>1 ;
    if(i <= mid)
        update(ch,i,l,mid,cur<<1);
    else
        update(ch,i,mid+1,r,cur<<1|1);
    Getsum(ch,cur);
}
//删除字符ch的第n个
int deleted(int ch, int n, int l,int r,int cur){//n代表第n个字母ch
    if( l == r){
        a[ch][cur] = 0 ;
        return l ;
    }
    int mid = ( l +  r) >>1 ,ans ;
    if(n <= a[t][cur<<1])
        ans = deleted()(ch,n,l,mid,cur<<1);
    else {
        ans = deleted(ch,n -a[ch][cur<<1],mid+1,r,cur<<1|1);
    }
    Getsum(ch,cur);
    return ans ;
}
int main()
{
    int k,m;
    while(scanf("%d %s%d",&k,s+1,&m)!=EOF){
        mem0(vis);mem0(a);
        int len = strlen(s+1);
        int n = len*k,j,i;
        for(j = len+1;--k;){
            for( i = 1; i <= len ; i++)
                s[j++]=s[i];
        }
        s[j]=0;
        for(int i = 1 ;  s[i] ; i++){
            update(s[i]-'a',i,1,n,1);
        }
        char c;
        while(m--){
            scanf("%d %c",&k,&c);
            int num = deleted(c-'a',k,1,n,1);
            vis[num]=1;
        }
        for(int i = 1 ; s[i] ; i++)
            if(vis[i]==0)
            printf("%c",s[i]);
        puts("");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值