HDU 3308LCIS 线段树维护区间lcs

来源:互联网 发布:手机程序加密软件 编辑:程序博客网 时间:2024/05/04 09:10

题意:

给一个1~n的数组

操作i把下标为x的值更新为y

操作ii查询区间 x~y的lcs

具体分析写在代码里

///参考讨论版

ACcode:

#include <cstdio>#include <algorithm>#define tmp (st<<1)#define mid ((l+r)>>1)#define lson l,mid,tmp#define rson mid+1,r,tmp|1#define len (r-l+1)#define maxn 100002using namespace std;int my[maxn],sum[maxn<<2],lsum[maxn<<2],rsum[maxn<<2];inline void push_up(int st,int l,int r){    lsum[st]=lsum[tmp];    rsum[st]=rsum[tmp|1];    sum[st]=max(sum[tmp],sum[tmp|1]);    if(my[mid]<my[mid+1]){///如果第mid+1大于mid 那么对于左子树的右lcs和右子树的左lcs可以合并        if(lsum[st]==len-(len>>1))lsum[st]+=lsum[tmp|1];        if(rsum[st]==len>>1)rsum[st]+=rsum[tmp];                 sum[st]=max(sum[st],lsum[tmp|1]+rsum[tmp]);    }}inline void build(int l,int r,int st){    if(l==r){        sum[st]=lsum[st]=rsum[st]=1;        return ;    }    build(lson);    build(rson);    push_up(st,l,r);}inline void updata(int t,int l,int r,int st){    if(l==r)return ;    if(t<=mid)updata(t,lson);    if(t>mid)updata(t,rson);    push_up(st,l,r);}inline int query(int L,int R,int l,int r,int st){    if(L<=l&&r<=R)return sum[st];    if(R<=mid)return query(L,R,lson);    if(L>mid)return query(L,R,rson);    int ans,lans,rans;    lans=query(L,R,lson);    rans=query(L,R,rson);    ans=max(lans,rans);    if(my[mid]<my[mid+1]){///同上        int temp=min(rsum[tmp],mid-L+1)+min(lsum[tmp|1],R-mid);        ans=max(ans,temp);    }    return ans;}int main(){    int loop,n,q,x,y;    char str[4];    scanf("%d",&loop);    while(loop--){        scanf("%d%d",&n,&q);        for(int i=1;i<=n;++i)scanf("%d",&my[i]);        build(1,n,1);        while(q--){            scanf("%s%d%d",str,&x,&y);            if(str[0]=='Q')                printf("%d\n",query(++x,++y,1,n,1));            else{                my[++x]=y;                updata(x,1,n,1);            }        }    }    return 0;}


0 0
原创粉丝点击