HDU3308(LCIS) 线段树好题
Posted Kurokey
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU3308(LCIS) 线段树好题相关的知识,希望对你有一定的参考价值。
题目链接:传送门
题目大意:给你n个数,m个操作。操作有两种:1.U x y 将数组第x位变为y 2. Q x y 问数组第x位到第y位连续最长子序列的长度。对于每次询问,输出一个答案
题目思路:线段树单点修改区间合并
这道题题目好在对pushup的理解,我们在向上更新的时候有注意情况的区分
1.如果左区间的最右边的值小于右区间最左边的值,则有一个待定答案是左儿子的右区间+右儿子的左区间
2.如果不符合第一个条件,则有一个待定答案是左区间最大值和右区间最大值中较大的那一个。
有一点要特别注意:如果当前区间中所有的值都符合上升序列,那么更新它的父节点时,它可以加上其他区间的边界值而进行扩充
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <cstring> #include <stack> #include <cctype> #include <queue> #include <string> #include <vector> #include <set> #include <map> #include <climits> #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define fi first #define se second #define ping(x,y) ((x-y)*(x-y)) #define mst(x,y) memset(x,y,sizeof(x)) #define mcp(x,y) memcpy(x,y,sizeof(y)) using namespace std; #define gamma 0.5772156649015328606065120 #define MOD 1000000007 #define inf 0x3f3f3f3f #define N 100005 #define maxn 50005 typedef pair<int,int> PII; typedef long long LL; const double pi=acos(-1.0); const double e=2.718281828459; int n,m,k,x,y; int no[N<<2],ls[N<<2],rs[N<<2]; int a[N]; inline void pushup(int rt,int l,int r){ int mid=l+r>>1; ls[rt]=ls[rt<<1];rs[rt]=rs[rt<<1|1]; no[rt]=max(no[rt<<1],no[rt<<1|1]); if(a[mid]<a[mid+1]){ if(ls[rt]==mid-l+1)ls[rt]+=ls[rt<<1|1]; if(rs[rt]==r-mid)rs[rt]+=rs[rt<<1]; no[rt]=max(no[rt],ls[rt<<1|1]+rs[rt<<1]); } } void build(int rt,int l,int r){ if(l==r){ no[rt]=ls[rt]=rs[rt]=1; return; } int mid=l+r>>1; build(lson);build(rson); pushup(rt,l,r); } void add(int rt,int l,int r){ if(l==r){return;} int mid=l+r>>1; if(x<=mid)add(lson); else add(rson); pushup(rt,l,r); } int query(int rt,int l,int r){ if(x<=l&&r<=y)return no[rt]; int mid=l+r>>1; if(y<=mid)return query(lson); if(x>mid)return query(rson); int t1=query(lson); int t2=query(rson); int ans=max(t1,t2); if(a[mid]<a[mid+1]){ ans=max(ans,(min(ls[rt<<1|1],y-mid)+min(rs[rt<<1],mid+1-x))); } return ans; } int main(){ int i,j,group; scanf("%d",&group); while(group--){ char str[5]; scanf("%d%d",&n,&m); for(i=1;i<=n;++i)scanf("%d",&a[i]); build(1,1,n); while(m--){ scanf("%s%d%d",str,&x,&y); ++x; if(str[0]==‘U‘){a[x]=y;add(1,1,n);} else{++y;printf("%d\n",query(1,1,n));} } } return 0; }
以上是关于HDU3308(LCIS) 线段树好题的主要内容,如果未能解决你的问题,请参考以下文章