考试题string——线段树。
生活随笔
收集整理的這篇文章主要介紹了
考试题string——线段树。
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
string
【題目描述】
給定一個由小寫字母組成的字符串 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
【數據范圍】
對于 40%的數據,n,m<=1000。
對于 100%的數據,n,m<=100000。
?
題解:
正解不明,但可以寫出nlogn*26*26的線段樹(然而只比暴力多10分)。
看到一共只有26個字母,考慮枚舉每個字母,統計在區間內部的個數,那么對于每種字母,顯然如果按順序排序,那么顯然是從a~z,一個一個區間覆蓋,區間清空。
線段樹實現,當然lz打的是區間覆蓋的標記,只要當前這個節點的元素值是什么,那么其他兒子節點的元素值就什么,就實現了區間清空和區間加法。
?
代碼:
#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; }?
轉載于:https://www.cnblogs.com/renjianshige/p/7643220.html
總結
以上是生活随笔為你收集整理的考试题string——线段树。的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一个APP“感知”北京门头沟的城市智慧
- 下一篇: ASP.NET中 DropDownLis