【NOIP模擬題目】string
阿新 • • 發佈:2020-09-14
題目描述:
給定一個由小寫字母組成的字串s。
有m次操作,每次操作給定3個引數l,r,x。
如果x = 1,將s[l] s[r]升序排序;
如果x = 0,將s[l] s[r]降序排序。
你需要求出最終序列。
輸入格式:
第一行兩個整數n,m。
第二行一個字串s。
接下來m行每行三個整數x,l,r。
輸出格式:
一行一個字串表示答案。
輸入樣例:
5 2
cabcd
1 3 1
3 5 0
輸出樣例:
abdcc
資料範圍:
對於100%的資料,n,m ≤ 100000。
思路
- 數字代替字母,每一次操作取出區間所有數字再填入,線段樹實現
- 有關清零,每一次getcol就順便將lazy標記清零,但不能在f陣列加時清零,會錯
- 這篇題解似乎比較詳細
程式碼
#include <iostream> #include <cstdio> #include <cstring> #define maxn 100005 using namespace std; struct fdfdfd{int l,r,val;}a[maxn<<2]; int n,m,f[30]; string st; void pushup(int x){if(a[x<<1].val==a[x<<1|1].val) a[x].val=a[x<<1].val;} void build(int x,int left,int right) { a[x].l=left; a[x].r=right; if(left==right) {a[x].val=st[left-1]-'a'+1; return;} int mid=(left+right)>>1; build(x<<1,left,mid); build(x<<1|1,mid+1,right); pushup(x); } void getcol(int x,int left,int right) { if(a[x].r<left||a[x].l>right) return; if(left<=a[x].l&&right>=a[x].r&&a[x].val) {f[a[x].val]+=a[x].r-a[x].l+1; return;} if(a[x].val) a[x<<1].val=a[x<<1|1].val=a[x].val; getcol(x<<1,left,right); getcol(x<<1|1,left,right); } void modify(int x,int left,int right,int d) { if(a[x].r<left||a[x].l>right) return; if(left<=a[x].l&&right>=a[x].r) {a[x].val=d; return;} if(a[x].val) a[x<<1].val=a[x<<1|1].val=a[x].val,a[x].val=0; modify(x<<1,left,right,d); modify(x<<1|1,left,right,d); pushup(x); } void print(int x) { if(a[x].val) { for(int i=a[x].l;i<=a[x].r;++i) printf("%c",a[x].val+'a'-1); return; } print(x<<1); print(x<<1|1); } int main() { scanf("%d%d",&n,&m); cin>>st; build(1,1,n); for(int i=1,l,r,x;i<=m;++i) { scanf("%d%d%d",&l,&r,&x); memset(f,0,sizeof(f)); getcol(1,l,r); if(x) { for(int j=1;j<=26;++j) if(f[j]) modify(1,l,l+f[j]-1,j),l+=f[j]; } else { for(int j=26;j>=1;--j) if(f[j]) modify(1,l,l+f[j]-1,j),l+=f[j]; } } print(1); return 0; }