SWUST OJ 2285
阿新 • • 發佈:2019-01-05
【解題方法】線段樹區間合併典型題,維護區間左端點開始最大值,右端點結束最大值,以及整體最大值,還需要維護一下區間左端點和右端點的值,這樣合併就方便了。
【我的這份程式碼還是比較快的,在本oj跑到了第一名】
【AC 程式碼】
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 100005; struct node{ int l,r,len; int lsum,rsum,msum; int lv,rv,v; }Tree[maxn<<2]; char s[maxn]; int a[maxn]; void pushup(int rt) { Tree[rt].lv = Tree[rt*2].lv; Tree[rt].rv = Tree[rt*2+1].rv; Tree[rt].lsum = Tree[rt*2].lsum; Tree[rt].rsum = Tree[rt*2+1].rsum; if(Tree[rt*2].lsum==Tree[rt*2].len && Tree[rt*2].rv<=Tree[rt*2+1].lv) Tree[rt].lsum = Tree[rt*2].lsum+Tree[rt*2+1].lsum; if(Tree[rt*2+1].rsum==Tree[rt*2+1].len && Tree[rt*2].rv<=Tree[rt*2+1].lv) Tree[rt].rsum = Tree[rt*2].rsum+Tree[rt*2+1].rsum; Tree[rt].msum = max(Tree[rt*2].msum,Tree[rt*2+1].msum); if(Tree[rt*2].rv<=Tree[rt*2+1].lv) Tree[rt].msum = max(Tree[rt].msum,Tree[rt*2].rsum+Tree[rt*2+1].lsum); } void pushdown(int rt) { if(Tree[rt].v) { Tree[rt*2].lsum=Tree[rt*2].rsum=Tree[rt*2].msum=Tree[rt*2].len; Tree[rt*2+1].lsum=Tree[rt*2+1].rsum=Tree[rt*2+1].msum=Tree[rt*2+1].len; Tree[rt*2].v=Tree[rt*2+1].v=Tree[rt].v; Tree[rt*2].lv=Tree[rt*2+1].lv=Tree[rt].v; Tree[rt*2].rv=Tree[rt*2+1].rv=Tree[rt].v; Tree[rt].v = 0; } } void Build(int l,int r,int rt) { Tree[rt].l = l,Tree[rt].r = r; Tree[rt].len = r-l+1; Tree[rt].v = 0; if(l==r) { Tree[rt].lsum=Tree[rt].rsum=Tree[rt].msum=1; Tree[rt].lv=Tree[rt].rv=a[l]; return ; } int mid = (l+r)/2; Build(l,mid,rt*2); Build(mid+1,r,rt*2+1); pushup(rt); } void update(int L,int R,int v,int rt) { if(L==Tree[rt].l&&Tree[rt].r==R) { Tree[rt].lv=Tree[rt].rv=Tree[rt].v=v; Tree[rt].lsum=Tree[rt].rsum=Tree[rt].msum=Tree[rt].len; return ; } pushdown(rt); int mid=(Tree[rt].l+Tree[rt].r)/2; if(R<=mid) update(L,R,v,rt*2); else if(L>mid) update(L,R,v,rt*2+1); else{ update(L,mid,v,rt*2); update(mid+1,R,v,rt*2+1); } pushup(rt); } int queryans(int L,int R,int rt) { if(L==Tree[rt].l&&Tree[rt].r==R) { return Tree[rt].msum; } pushdown(rt); int mid = (Tree[rt].l+Tree[rt].r)/2; if(R<=mid) return queryans(L,R,rt*2); else if(L>mid) return queryans(L,R,rt*2+1); else{ int ret = max(queryans(L,mid,rt*2),queryans(mid+1,R,rt*2+1)); if(Tree[rt*2].rv<=Tree[rt*2+1].lv){ ret = max(ret,min(Tree[rt*2].rsum,mid-L+1)+min(Tree[rt*2+1].lsum,R-mid)); } return ret; } } int main() { int T; scanf("%d",&T); while(T--) { scanf("%s",s+1); int n = strlen(s+1); for(int i=1 ;i<=n; i++) a[i] = s[i]-'a'+1; Build(1,n,1); int q; scanf("%d",&q); char op1[3],op2[3]; int l,r; while(q--) { scanf("%s%d%d",op1,&l,&r); if(l>r) swap(l,r); if(op1[0]=='Q'){ printf("%d\n",queryans(l,r,1)); } else{ scanf("%s",op2); update(l,r,op2[0]-'a'+1,1); } } } return 0; }