杭电3308

来源:互联网 发布:数控车床编程操作方法 编辑:程序博客网 时间:2024/06/06 01:01
/*
杭电3308  LCIS
真是做题伤身呀,看了博客,写了一中午,wrong,最后
竟然错在了一个1上
这是一道区间合并题
有两种操作
U A B
第A个数改为B
Q A B
输出A B 之间最长连续递增子序列
这一题的难点重要在merge(区间合并上)
*/

#include<stdio.h>#include<algorithm>using namespace std;#define MAXN 110008typedef struct{    __int64 l,r,lmax,rmax,max;} T;/* l,r左右边界 lmax 记录以左边界为起点的最长连续递增子序列 rmax 记录以右边界为终点的最长连续递增子序列 max   此区间最长连续子序列*/T node[MAXN*4];__int64 S[MAXN];void merge(__int64 i){    node[i].max=max(node[2*i].max,node[2*i+1].max);   //左孩子的右边界小于右孩子的左边界,二者合并,更新最大值   if(S[node[2*i].r]<S[node[2*i+1].l])        node[i].max=max(node[i].max,node[2*i].rmax+node[2*i+1].lmax);    //如果左孩子连续递增,且左孩子的右边界小于右孩子的左边界,二者合并    //更新此节点的lmax   if(node[2*i].max==node[2*i].r-node[2*i].l+1&&S[node[2*i].r]<S[node[2*i+1].l])       node[i].lmax=node[2*i].max+node[2*i+1].lmax;   else  node[i].lmax=node[2*i].lmax;   //如果右孩子连续递增,且左孩子的右边界小于右孩子的左边界,二者合并    //更新此节点的rmax,   if(node[2*i+1].max==node[2*i+1].r-node[2*i+1].l+1&&S[node[2*i].r]<S[node[2*i+1].l])        node[i].rmax=node[2*i+1].max+node[2*i].rmax;   else node[i].rmax=node[2*i+1].rmax;}//merge函数区间合并void Build_tree(__int64 i,__int64 l,__int64 r){    node[i].l=l;node[i].r=r;    if(l==r){        node[i].max=node[i].lmax=node[i].rmax=1;        return ;    }    __int64 mid=(l+r)/2;    Build_tree(2*i,l,mid);Build_tree(2*i+1,mid+1,r);    merge(i);}__int64 Qurry(__int64 i,__int64 l,__int64 r){        if(node[i].l==l&&node[i].r==r) return node[i].max;    __int64 mid=(node[i].l+node[i].r)/2;    if(r<=mid)return Qurry(2*i,l,r);    else if(l>mid) return Qurry(2*i+1,l,r);    //以上的查询都很容易理解,以下跨区间查询    else{    __int64 k,ll,rr;    k=max(Qurry(2*i,l,mid),Qurry(2*i+1,mid+1,r));    if(S[mid]>=S[mid+1])return k;//这两个区间不能合并    ll=node[2*i].rmax>mid-l+1?mid-l+1:node[2*i].rmax;    rr=node[2*i+1].lmax>r-mid?r-mid:node[2*i+1].lmax;    //可以合并    return max(k,ll+rr);    }}void Update(__int64 i,__int64 s){    if(node[i].l==s&&node[i].r==s)return ;    __int64 mid=(node[i].l+node[i].r)/2;    if(s<=mid) Update(2*i,s);    else  Update(2*i+1,s);    merge(i);}int main(){       __int64 t,n,m,i;    scanf("%I64d",&t);    while(t--){     scanf("%I64d%I64d",&n,&m);     for(i=0;i<n;i++)scanf("%I64d",&S[i]);     Build_tree(1,0,n-1);     char str[3];     __int64 x,y;     for(i=0;i<m;i++){       scanf("%s%I64d%I64d",str,&x,&y);       if(str[0]=='U'){S[x]=y;Update(1,x);}       if(str[0]=='Q')printf("%I64d\n",Qurry(1,x,y));       }    }}


原创粉丝点击