您的位置:首页 > 其它

HDU 3308 LCIS(线段树区间合并 单点更新)

2015-08-10 10:04 507 查看
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<sstream>
#include<fstream>
#include<vector>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<queue>
#define LL long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1 | 1
using namespace std;
const int maxn=100005,inf=1<<29;
int lsum[maxn<<2],rsum[maxn<<2],msum[maxn<<2],ln[maxn<<2],rn[maxn<<2];
void PushUp(int rt,int m)//利用子节点信息更新父节点
{
    lsum[rt]=lsum[rt<<1];//根节点从左边其的最长区间至少等于左儿子从左边起得最长区间
    rsum[rt]=rsum[rt<<1|1];
    msum[rt]=max(msum[rt<<1],msum[rt<<1|1]);
    ln[rt]=ln[rt<<1];
    rn[rt]=rn[rt<<1|1];
    if(rn[rt<<1]<ln[rt<<1|1])//左儿子区间右端点比右儿子区间左端点小
    {
        if(lsum[rt]==m-(m>>1)) lsum[rt]+=lsum[rt<<1|1];
        if(rsum[rt]==(m>>1)) rsum[rt]+=rsum[rt<<1];
        msum[rt]=max(msum[rt],rsum[rt<<1]+lsum[rt<<1|1]);
    }
}
void build(int l,int r,int rt)//建树
{
    if(l==r)
    {
        scanf("%d",&ln[rt]);
        //printf("[%d,%d] = %d\n",l,r,ln[rt]);
        rn[rt]=ln[rt];
        lsum[rt]=rsum[rt]=msum[rt]=1;
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    PushUp(rt,r-l+1);
    //printf("msum[%d,%d] = %d\n",l,r,msum[rt]);
}
void update(int p,int x,int l,int r,int rt)//单点更新
{
    if(l==r)
    {
        lsum[rt]=rsum[rt]=msum[rt]=1;
        ln[rt]=rn[rt]=x;
        return ;
    }
    int m=(l+r)>>1;
    if(p<=m) update(p,x,lson);
    else update(p,x,rson);
    PushUp(rt,r-l+1);
}
int Query(int L,int R,int l,int r,int rt)
{
    //区间是叶子节点或都可用或都不可用直接返回
    if(L<=l&&r<=R) return msum[rt];
    //if(l==r||msum[rt]==0||msum[rt]==r-l+1) return msum[rt];
    int ans=0;
    int m=(l+r)>>1;
    if(L<=m) ans=max(ans,Query(L,R,lson));
    if(R>m) ans=max(ans,Query(L,R,rson));
    if(rn[rt<<1]<ln[rt<<1|1]) ans=max(ans,min(rsum[rt<<1],m-L+1)+min(lsum[rt<<1|1],R-m));//不能越了区间[L,R]的界
    //printf("msum[%d,%d] = %d ans=%d\n",l,r,msum[rt],ans);
    return ans;
    //return max(ans,rsum[rt<<1]+lsum[rt<<1|1]);
}
int main()
{
     //freopen("in.txt","r",stdin);
     //freopen("out.txt","w",stdout);
     //srand(time(NULL));
     int n,m,x,y,t;
     scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        char op[5];
        build(1,n,1);
        for(int i=0;i<m;i++)
        {
            scanf("%s%d%d",op,&x,&y);
            if(op[0]=='U') update(x+1,y,1,n,1);
            else printf("%d\n",Query(x+1,y+1,1,n,1));
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: