hdu 3308 LCIS

来源:互联网 发布:淘宝客api调用实例php 编辑:程序博客网 时间:2024/04/30 07:31

/*

题型:线段树;

解题思路:

    在线段树的节点上保存lmax,rmax,max三个值,lmax表示从该节点左端点数递增的最长长度,rmax表示终点是该节点的右端点的最长长度,max表示该区间的最长长度

更新就是:如果左孩子的右端点小于右孩子的左端点,那么就合并左孩子rmax和右孩子的lmax;查询时和更新相似;

 

代码如下:

*/

 

#include<stdio.h>#include<string.h>struct node{int l,r,x;node(){l=r=x=1;}node(int a,int b,int c):l(a),r(b),x(c){}void set(int a,int b,int c){ l=a; r=b; x=c;}}sum[400010];int Max(int a,int b){ return a<b?b:a;}int S[100010];void build(int i,int l,int r){int mid,ans;if(l==r){sum[i].set(1,1,1);return;}int a,b;mid=(l+r)/2;build(i<<1,l,mid);build(i<<1|1,mid+1,r);a=sum[i<<1].l;b=sum[i<<1|1].r;ans=Max(sum[i<<1].x,sum[i<<1|1].x);if(S[mid]<S[mid+1]){ans=Max(ans,sum[i<<1].r+sum[i<<1|1].l);if(a==mid-l+1) a+=sum[i<<1|1].l;if(b==r-mid) b+=sum[i<<1].r;}sum[i].set(a,b,ans);}void update(int i,int l,int r,int p,int v){if(l==r){S[l]=v;return ;}int mid=(l+r)/2,ans,a,b;if(p<=mid)update(i<<1,l,mid,p,v);else update(i<<1|1,mid+1,r,p,v);a=sum[i<<1].l;b=sum[i<<1|1].r;ans=Max(sum[i<<1].x,sum[i<<1|1].x);if(S[mid]<S[mid+1]){ans=Max(ans,sum[i<<1].r+sum[i<<1|1].l);if(a==mid-l+1) a+=sum[i<<1|1].l;if(b==r-mid)   b+=sum[i<<1].r;}sum[i].set(a,b,ans);}int query(int i,int l,int r,int a,int b,int &ml,int &mr){if(l==a&&r==b){mr=sum[i].r;ml=sum[i].l;return sum[i].x;}int mid=(l+r)/2,ans,mml[2],mmr[2];if(b<=mid)return query(i<<1,l,mid,a,b,ml,mr);if(a>mid) return query(i<<1|1,mid+1,r,a,b,ml,mr);ans=Max(query(i<<1,l,mid,a,mid,mml[0],mmr[0]),query(i<<1|1,mid+1,r,mid+1,b,mml[1],mmr[1]));ml=mml[0];mr=mmr[1];if(S[mid]<S[mid+1]){ans=Max(ans,mmr[0]+mml[1]);if(ml==mid-a+1) ml+=mml[1];if(mr==b-mid) mr+=mmr[0];}return ans;}int main(){char op[5];int cas,n,m,i,a,b,x,y;scanf("%d",&cas);while(cas--){scanf("%d%d",&n,&m);for(i=1;i<=n;i++)scanf("%d",&S[i]);build(1,1,n);while(m--){scanf("%s%d%d",op,&a,&b);a++;if(op[0]=='U')update(1,1,n,a,b);else {b++;printf("%d\n",query(1,1,n,a,b,x,y));}}}return 0;}


 

原创粉丝点击