【CodeForces】F. Letters Removing
阿新 • • 發佈:2017-12-19
blog ons hid nbsp 題意 style sin n) ret
【題目】F. Letters Removing
【題意】給定只含小寫字母、大寫字母和數字的字符串,每次給定一個範圍要求刪除[l,r]內的字符c(l和r具體位置隨刪除變動),求m次操作後的字符串。n<=2*10^5。
【算法】樹狀數組+平衡樹(set)
【題解】因為坐標是序列變動後的,動態坐標可以轉化為找到第l個存在的數字到第r個存在的數字之間的範圍。
將序列中存在記為1,刪除記為0,轉化為找前綴和恰好為l和r的位置,這是樹狀數組的經典操作,詳見這篇題解介紹的方法(簡單的排名功能)
找到l和r在原數組的位置後,接下來需要刪除。因為字符個數不多,對每個字符開一個set記錄位置,然後lower_bound後逐個刪除即可。
復雜度O(n log n)。
#include<cstdio> #include<cstring> #include<set> #include<cctype> #include<algorithm> using namespace std; const int maxn=200010,M=62; int n,m,a[maxn],c[maxn]; char S[maxn],SS[10]; set<int>s[63]; set<int>::iterator it,itt; int read(){ char c;intView Codes=0,t=1; while(!isdigit(c=getchar()))if(c==‘-‘)t=-1; do{s=s*10+c-‘0‘;}while(isdigit(c=getchar())); return s*t; } #define lowbit(x) (x&-x) void modify(int x){for(int i=x;i<=n;i+=lowbit(i))c[i]--;} int ask(int x){int as=0;for(int i=x;i>=1;i-=lowbit(i))as+=c[i];return as;} int find(intx){ int num=0,p=0; for(int i=20;i>=0;i--)if(p+(1<<i)<=n&&num+c[p+(1<<i)]<x)num+=c[p+=(1<<i)]; return p+1; } int p(char c){ if(‘a‘<=c&&c<=‘z‘)return c-‘a‘+1; if(‘A‘<=c&&c<=‘Z‘)return c-‘A‘+27; return c-‘0‘+53; } int main(){ n=read();m=read(); scanf("%s",S+1); for(int i=1;i<=n;i++){ a[i]=p(S[i]); s[a[i]].insert(i); } for(int i=1;i<=n;i++)c[i+lowbit(i)]+=++c[i]; for(int i=1;i<=m;i++){ int l=find(read()),r=find(read()),x; scanf("%s",SS);x=p(SS[0]); it=s[x].lower_bound(l); while(it!=s[x].end()&&*it<=r)modify(*it),itt=it,it++,s[x].erase(itt); } for(int i=1;i<=n;i++)if(ask(i)-ask(i-1))printf("%c",S[i]); return 0; }
【CodeForces】F. Letters Removing