HDU - 3308(区间合并类)

只需单点修改和求区间最大连续上升序列长度。

那么,维护左的最大升长,右的最大降长,和区间最大升长。便可区间合并。因为查询的区间合并和上推区间合并动作一致,用一个node函数抽象一下就行了。

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define rep(i,n) for(int (i)=0;(i)<(n);i++)
#define Rep(i,n) for(int (i)=1;(i)<=(n);i++)

const int N = 111111;
int a[N];
struct node{
  int pre,suf,Max,l,r;
}b[N<<2];
node push_up(node A,node B){
  node te;
  te.l=A.l; te.r=B.r;
  te.Max = max(A.Max,B.Max);
  if(a[A.r]<a[B.l]) te.Max = max(te.Max,B.pre+A.suf);
  te.pre=A.pre;
  if(A.pre==A.r-A.l+1 && a[A.r]<a[B.l]) te.pre+=B.pre;
  te.suf=B.suf;
  if(B.suf==B.r-B.l+1 && a[A.r]<a[B.l]) te.suf+=A.suf;
  return te;
}
void build(int l,int r,int rt){
  if(l==r){
    scanf("%d",&a[l]);
    b[rt].pre=b[rt].suf=1;  b[rt].Max=1;
    b[rt].l=b[rt].r=r;
    return ;
  }
  int m=(l+r)>>1;
  build(lson);
  build(rson);
  b[rt] = push_up(b[rt<<1],b[rt<<1|1]);
}
void update(int l,int r,int rt,int p,int v){
  if(l==r){
     a[l] = v;
     return ;
  }
  int m=(l+r)>>1;
  if(p<=m) update(lson,p,v);
  else update(rson,p,v);
  b[rt] = push_up(b[rt<<1],b[rt<<1|1]);
}
node query(int l,int r,int rt,int L,int R){
  if(L<=l&&r<=R){
     return b[rt];
  }
  int m=(l+r)>>1;
  node res; int ok=0;
  if(L<=m) {res=query(lson,L,R); ok = 1;}
  if(R>m){
     if(ok) res=push_up(res,query(rson,L,R));
     else res=query(rson,L,R);
  }
  return res;
}
int n,m;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d %d",&n,&m);
        build(1,n,1);
        while(m--){
            char cmd[3];
            int x,y;
            scanf("%s %d %d",cmd,&x,&y);
            if(cmd[0]=='U'){
                update(1,n,1,x+1,y);
            }
            else {
                x++; y++;
                node res = query(1,n,1,x,y);
                printf("%d\n",res.Max);
            }
        }
    }
    return 0;
}


你可能感兴趣的:(HDU - 3308(区间合并类))