日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

考试题string——线段树。

發布時間:2025/6/15 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 考试题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——线段树。的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。