考试题string——线段树。
string
【題目描述】
給定一個(gè)由小寫字母組成的字符串 s。有 m 次操作,每次操作給
定 3 個(gè)參數(shù) l,r,x。如果 x=1,將 s[l]~s[r]升序排序;如果 x=0,將 s[l]~s[r]
降序排序。你需要求出最終序列。
【輸入數(shù)據(jù)】
第一行兩個(gè)整數(shù) n,m。第二行一個(gè)字符串 s。接下來 m 行每行三
個(gè)整數(shù) x,l,r。
【輸出數(shù)據(jù)】
一行一個(gè)字符串表示答案。
【樣例輸入】
5 2
cabcd
1 3 1
3 5 0
【樣例輸出】
abdcc
【數(shù)據(jù)范圍】
對(duì)于 40%的數(shù)據(jù),n,m<=1000。
對(duì)于 100%的數(shù)據(jù),n,m<=100000。
?
題解:
正解不明,但可以寫出nlogn*26*26的線段樹(然而只比暴力多10分)。
看到一共只有26個(gè)字母,考慮枚舉每個(gè)字母,統(tǒng)計(jì)在區(qū)間內(nèi)部的個(gè)數(shù),那么對(duì)于每種字母,顯然如果按順序排序,那么顯然是從a~z,一個(gè)一個(gè)區(qū)間覆蓋,區(qū)間清空。
線段樹實(shí)現(xiàn),當(dāng)然lz打的是區(qū)間覆蓋的標(biāo)記,只要當(dāng)前這個(gè)節(jié)點(diǎn)的元素值是什么,那么其他兒子節(jié)點(diǎn)的元素值就什么,就實(shí)現(xiàn)了區(qū)間清空和區(qū)間加法。
?
代碼:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <iostream> #define MAXN 110000 #define RG register using namespace std; struct node{int lz,l,r,sum[26]; }a[MAXN*4]; int n,q; char ch[MAXN]; int chuan[MAXN],tot[26];inline void pushup(int xv){for(int i=0;i<=25;i++) a[xv].sum[i]=a[xv*2].sum[i]+a[xv*2+1].sum[i]; }inline void pushdown(int xv,int x,int y){if(a[xv].lz){a[xv].lz=0;for(int i=0;i<=25;i++){if(a[xv].sum[i]==0) a[xv*2].sum[i]=a[xv*2+1].sum[i]=0;else a[xv*2].sum[i]=x,a[xv*2+1].sum[i]=y;}a[xv*2].lz=a[xv*2+1].lz=1;} }inline void build(int xv,int l,int r){if(l==r){a[xv].l=l,a[xv].r=r,a[xv].lz=0;memset(a[xv].sum,0,sizeof(a[xv].sum));a[xv].sum[chuan[l]]=1;return;}a[xv].l=l,a[xv].r=r;int mid=(l+r)/2;build(xv*2,l,mid),build(xv*2+1,mid+1,r);pushup(xv); }inline int query(int xv,int l,int r,int k){RG int L=a[xv].l,R=a[xv].r,mid=(L+R)/2;if(L==l&&R==r){return a[xv].sum[k];}pushdown(xv,mid-L+1,R-mid);if(r<=mid) return query(xv*2,l,r,k);else if(l>mid) return query(xv*2+1,l,r,k);else return query(xv*2,l,mid,k)+query(xv*2+1,mid+1,r,k); }inline void update(int xv,int l,int r,int k){RG int L=a[xv].l,R=a[xv].r,mid=(L+R)/2;if(l==L&&R==r){memset(a[xv].sum,0,sizeof(a[xv].sum));a[xv].sum[k]=r-l+1;a[xv].lz=1;return;}pushdown(xv,mid-L+1,R-mid);if(r<=mid) update(xv*2,l,r,k);else if(l>mid) update(xv*2+1,l,r,k);else update(xv*2,l,mid,k),update(xv*2+1,mid+1,r,k);pushup(xv); }inline int query2(int xv,int ps){RG int L=a[xv].l,R=a[xv].r,mid=(L+R)/2;if(L==R){for(int i=0;i<=25;i++)if(a[xv].sum[i]) return i;}pushdown(xv,mid-L+1,R-mid);if(ps<=mid) return query2(xv*2,ps);else return query2(xv*2+1,ps); }int main() {scanf("%d%d",&n,&q);scanf("%s",ch+1);for(int i=1;i<=n;i++) chuan[i]=ch[i]-'a';build(1,1,n);while(q--){int l,r,x;scanf("%d%d%d",&l,&r,&x);if(l>r) swap(l,r);memset(tot,0,sizeof(tot));for(int i=0;i<=25;i++) tot[i]+=query(1,l,r,i);if(x==1){int ll=l,rr=l-1;for(int i=0;i<=25;i++){if(tot[i]!=0){rr+=tot[i];update(1,ll,rr,i);ll=rr+1;}}}else{int ll=l,rr=l-1;for(int i=25;i>=0;i--){if(tot[i]!=0){rr+=tot[i];update(1,ll,rr,i);ll=rr+1;}}}}for(int i=1;i<=n;i++){printf("%c",query2(1,i)+'a');}return 0; }?
轉(zhuǎn)載于:https://www.cnblogs.com/renjianshige/p/7643220.html
總結(jié)
以上是生活随笔為你收集整理的考试题string——线段树。的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一个APP“感知”北京门头沟的城市智慧
- 下一篇: 保证java的jar包在后台运行