hdu 3308 LCIS (区间合并)

来源:互联网 发布:交朋友的软件 编辑:程序博客网 时间:2024/05/26 07:29

求区间最长最长上升序列长度,是线段树区间合并的典型题目。

维护左起最长,区间最长和右起最长三个值即可,因为要求上升序列,还要保存区间端点值。


#include<iostream>#include<algorithm>using namespace std;#define lson 2*o,l,mid#define rson 2*o+1,mid+1,r#define INF 1000000000const int maxn=400005;typedef long long ll;struct TREE{int len;int mmax,lmax,rmax,lnum,rnum;}tree[maxn];void pushup(int o){tree[o].len=tree[2*o].len+tree[2*o+1].len;tree[o].lnum=tree[2*o].lnum;tree[o].rnum=tree[2*o+1].rnum;tree[o].lmax=tree[2*o].lmax;tree[o].rmax=tree[2*o+1].rmax;tree[o].mmax=max(tree[2*o].mmax,tree[2*o+1].mmax);if(tree[2*o].rnum<tree[2*o+1].lnum){if(tree[2*o].lmax==tree[2*o].len){tree[o].lmax+=tree[2*o+1].lmax;}if(tree[2*o+1].rmax==tree[2*o+1].len)tree[o].rmax+=tree[2*o].rmax;tree[o].mmax=max(tree[o].mmax,tree[2*o].rmax+tree[2*o+1].lmax);}}void insert(int o,int l,int r,int a,int b,int c){if(a>r||b<l)return;if(a<=l&&r<=b){tree[o].len=r-l+1;tree[o].lnum=tree[o].rnum=c;tree[o].mmax=tree[o].rmax=tree[o].lmax=1;return;}int mid=(l+r)>>1;insert(lson,a,b,c);insert(rson,a,b,c);pushup(o);}int query(int o,int l,int r,int a,int b){if(a>r||b<l)return 0;if(a<=l&&r<=b){return tree[o].mmax;}int mid=(l+r)>>1;int ans=max(query(lson,a,b),query(rson,a,b));if(tree[2*o].rnum<tree[2*o+1].lnum){ans=max(ans,min(mid-a+1,tree[2*o].rmax)+min(b-mid,tree[2*o+1].lmax));}return ans;}int main(){int t=0;scanf("%d",&t);while(t--){memset(tree,0,sizeof(tree));int n,m,u;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%d",&u);insert(1,1,n,i,i,u);}getchar();getchar();char ch;int a,b;while(m--){scanf("%c%d%d",&ch,&a,&b);if(ch=='Q'){int ans=query(1,1,n,a+1,b+1);printf("%d\n",ans);}else {insert(1,1,n,a+1,a+1,b);}getchar();}}return 0;}


0 0
原创粉丝点击