给定长度n的字符串,m次操作,每次删去[l,r](对现字符串而言)中的所有字符c
然后我在比赛时想的是把每个字符的个数都统计一遍。。复杂度快要爆炸然而还是抱着侥幸心理写了下去(其实是我不会E),然后陷入了无尽的坑。。。
用半小时写出线段树(还好没出错)一交MLE。。。然后把叶子的儿子给砍掉了(这个优化以后还是能用得上滴。。),还不行。。再把满二叉树的节点求出来,然后还不行?!发现得缩到原来的一半才能把内存卡过去,于是把lazytag数组改成了bool,终于过了。。
然后看到别人的内存都不足我1/10才发现自己用了个傻逼做法,事实上删去字符的个数顶多n个,所以如果直接按点删除时间复杂度O(nlogn),于是根本就不用理会那么多字符,用树状数组维护个数,随便用个队列把要修改的点给找出来一个个改就可以了。。
线段树那个码那么辛苦还是贴一下吧qaq
树状数组:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inf 1e9
#define eps 1e-8
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define succ(x) (1<<x)
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define NM 200005
#define pi 3.141592653
#define nm 63
using namespace std;
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}
int n,m,_x,_y,_t,a[NM];
char s[NM],_s[NM];
queue<int >q[nm];
int tr(char c){
if(isdigit(c))return c-'0';
if(c>='a')return c-'a'+10;return c-'A'+36;
}
void add(int x,int t){while(x<=n)a[x]+=t,x+=lowbit(x);}
int sum(int x){return x?a[x]+sum(x-lowbit(x)):0;}
int find(int x){
int l=1,r=n;
while(l<r){
int t=l+r>>1;
if(sum(t)<x)l=t+1;else r=t;
}
return l;
}
int main(){
n=read();m=read();
scanf("%s",s);strcpy(_s,s);
inc(i,1,n)
add(i,1),q[tr(s[i-1])].push(i);
inc(i,1,m){
_x=find(read());_y=find(read());scanf("%s",s);
_t=tr(s[0]);
if(q[_t].empty())continue;
int t=0;
while(!q[_t].empty()&&t<q[_t].front()){
t=q[_t].front();q[_t].pop();
if(_x<=t&&t<=_y)add(t,-1);else q[_t].push(t);
}
}
inc(i,1,n)if(a[i]){printf("%c",_s[i-1]);add(i,-1);}
putchar('\n');
return 0;
}
线段树:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<cmath>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inf 1e9
#define eps 1e-8
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define succ(x) (1<<x)
#define lowbit(x) (x&&(-x))
#define sqr(x) ((x)*(x))
#define NM 200005
#define pi 3.141592653
#define nm 63
using namespace std;
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}
int n,m,_x,_y,M;
char s[NM];
struct info{
int s,size,a[nm];
bool tag[nm];
info operator+(const info&o){
info f;f.s=s+o.s;mem(f.tag);f.size=size+o.size;
inc(i,1,M)f.a[i]=o.a[i]+this->a[i];
return f;
}
}T[524300];
void pushdown(int x){
if(T[x].size==1)return;
inc(i,1,M)if(T[x].tag[i]){
T[x<<1].tag[i]=T[x<<1|1].tag[i]=1;
T[x<<1].s-=T[x<<1].a[i];T[x<<1|1].s-=T[x<<1|1].a[i];
T[x<<1].a[i]=0;T[x<<1|1].a[i]=0;
T[x].tag[i]=0;
}
}
int tran(char c){
if(isdigit(c))return c-'0'+1;
if('a'<=c&&c<='z')return c-'a'+10+1;
return c-'A'+1+10+26;
}
void build(int i,int x,int y){
int t=x+y>>1;
if(x==y){
T[i].s=1;T[i].size=1;
T[i].a[tran(s[x-1])]=1;
return;
}
build(i<<1,x,t);build(i<<1|1,t+1,y);
T[i]=T[i<<1]+T[i<<1|1];
}
void mod(int i,int x,int y){
int t=x+y>>1;
if(_y<x||y<_x)return;
if(_x<=x&&y<=_y){
T[i].s-=T[i].a[tran(s[0])];
T[i].tag[tran(s[0])]=1;
T[i].a[tran(s[0])]=0;
return;
}
pushdown(i);
mod(i<<1,x,t);mod(i<<1|1,t+1,y);
T[i]=T[i<<1]+T[i<<1|1];
}
int find(int i,int x,int y){
int t=x+y>>1;
pushdown(i);
if(x==y)return x;
if(_x<=T[i<<1].s)return find(i<<1,x,t);
_x-=T[i<<1].s;return find(i<<1|1,t+1,y);
}
void out(int i,int x,int y){
int t=x+y>>1;
pushdown(i);
if(T[i].s==0)return;
if(x==y)inc(j,1,M)if(T[i].a[j]){
if(j<=10)putchar('0'+j-1);
else if(j<=36)putchar('a'+j-11);
else putchar('A'+j-37);
return;
}
out(i<<1,x,t);out(i<<1|1,t+1,y);
}
int main(){
// freopen("data.in","r",stdin);
M=26+26+10;
n=read();m=read();
scanf("%s",s);
build(1,1,n);
inc(i,1,m){
_x=read();
_y=find(1,1,n);
_x=read();
_x=find(1,1,n);
swap(_x,_y);
scanf("%s",s);
mod(1,1,n);
}
out(1,1,n);putchar('\n');
return 0;
}
Petya has a string of length n consisting of small and large English letters and digits.
He performs m operations. Each operation is described with two integers l and r and a character c: Petya removes from the string all characters c on positions between l and r, inclusive. It's obvious that the length of the string remains the same or decreases after each operation.
Find how the string will look like after Petya performs all m operations.
The first string contains two integers n and m (1 ≤ n, m ≤ 2·105) — the length of the string and the number of operations.
The second line contains the string of length n, consisting of small and large English letters and digits. Positions in the string are enumerated from 1.
Each of the next m lines contains two integers l and r (1 ≤ l ≤ r), followed by a character c, which is a small or large English letter or a digit. This line describes one operation. It is guaranteed that r doesn't exceed the length of the string s before current operation.
Print the string Petya will obtain after performing all m operations. If the strings becomes empty after all operations, print an empty line.
4 2 abac 1 3 a 2 2 c
b
3 2 A0z 1 3 0 1 1 z
Az
10 4 agtFrgF4aF 2 5 g 4 9 F 1 5 4 1 7 a
tFrg4
9 5 aAAaBBccD 1 4 a 5 6 c 2 3 B 4 4 D 2 3 A
AB
In the first example during the first operation both letters 'a' are removed, so the string becomes "bc". During the second operation the letter 'c' (on the second position) is removed, and the string becomes "b".
In the second example during the first operation Petya removes '0' from the second position. After that the string becomes "Az". During the second operations the string doesn't change.