hdu 3308 LCIS (线段树区间合并)
来源:互联网 发布:mac 复制照片到u盘 编辑:程序博客网 时间:2024/05/18 11:48
Problem Description
Given n integers.
You have two operations:
U A B: replace the Ath number by B. (index counting from 0)
Q A B: output the length of the longest consecutive increasing subsequence (LCIS) in [a, b].
Input
T in the first line, indicating the case number.
Each case starts with two integers n , m(0< n,m<=105).
The next line has n integers(0<=val<=105).
The next m lines each has an operation:
U A B(0<=A,n , 0<=B=105)
OR
Q A B(0<=A<=B< n).
Output
For each Q, output the answer.
Sample Input
1
10 10
7 7 3 3 5 9 9 8 1 8
Q 6 6
U 3 4
Q 0 1
Q 0 5
Q 4 7
Q 3 5
Q 0 2
Q 4 6
U 6 10
Q 0 9
Sample Output
1
1
4
2
3
1
2
5
题目大意:
求出查询一栏中给定的区间内最长连续递增序列的长度
解题思路:
因为同时要更新数据,因此需要建树,进行基础的区间合并,没有坑点,适合作为模板。
#include<iostream>using namespace std;#define imax 1000005int n,m,s[imax];struct node{ int l,r,len; //左右边界与连续的长度 int ln,rn; //左右边界的值 int ls,rs,ms; //左右最大的LICS和区间最大的LICS }f[imax*3];void pushup(int t) //区间合并处理 { f[t].ls=f[t*2].ls; f[t].rs=f[t*2+1].rs; f[t].ln=f[t*2].ln; f[t].rn=f[t*2+1].rn; f[t].ms=max(f[t*2].ms,f[t*2+1].ms); //更新当前节点的区间最大LICS if(f[t*2].rn<f[t*2+1].ln) //如果左子树的右边界小于右子树的左边界值,要合并左子树的右边界和右子树的左边界进行计算 { if(f[t*2].ls==f[t*2].len) //如果左子树的LICS长度等于左子树区间长度 f[t].ls+=f[t*2+1].ls; //那么就可以把右子树的左子树最大的LICS值累加到左子树的ls值中 if(f[t*2+1].rs==f[t*2+1].len) //右子树亦然 f[t].rs+=f[t*2].rs; f[t].ms=max(f[t].ms,f[t*2].rs+f[t*2+1].ls); //然后再更新一次当前节点的区间最大LICS }}void build(int t,int l,int r){ f[t].l=l; f[t].r=r; f[t].len=r-l+1; if(l==r) { f[t].ln=f[t].rn=s[l]; f[t].ls=f[t].rs=f[t].ms=1; //建树赋值 return ; } int mid=(l+r)/2; build(t*2,l,mid); build(t*2+1,mid+1,r); pushup(t); } void insert(int t,int num,int c){ if(f[t].l==f[t].r) { f[t].ln=f[t].rn=c; return ; } int mid=(f[t].l+f[t].r)/2; if(num<=mid) insert(t*2,num,c); else insert(t*2+1,num,c); pushup(t);}int query(int t,int l,int r){ if(f[t].l>=l&&f[t].r<=r) return f[t].ms; int mid=(f[t].l+f[t].r)/2,ans=0; if(l<=mid) //如果区间包含当前节点左子树的一部分值 ans=max(ans,query(t*2,l,r)); //深入当前节点的左子树查询 if(r>mid) //如果区间包含当前节点右子树的一部分值 ans=max(ans,query(t*2+1,l,r)); //深入当前节点的右子树查询 if(f[t*2].rn<f[t*2+1].ln) //如果左子树的右边界小于右子树的左边界值, ans=max(ans,min(mid-l+1,f[t*2].rs)+min(r-mid,f[t*2+1].ls)); //更新一次ans的值 return ans;}int main(){ int t,l,r,a,b; char ss[10]; cin>>t; while(t--) { cin>>n>>m; for(int i=1;i<=n;i++) cin>>s[i]; build(1,1,n); while(m--) { cin>>ss>>a>>b; if(ss[0]=='Q') cout<<query(1,a+1,b+1)<<endl; else insert(1,a+1,b); } } return 0; }
- hdu 3308 LCIS 线段树 区间合并
- hdu 3308LCIS 线段树 区间合并
- [HDU 3308]LCIS[线段树][区间合并]
- hdu 3308 LCIS(线段树区间合并)
- HDU 3308 LCIS 线段树区间合并
- HDU 3308 LCIS(线段树区间合并)
- hdu 3308 LCIS (线段树+单点更新+区间合并)
- 【HDU】3308 LCIS (线段树-区间合并)
- HDU 3308 LCIS(线段树区间合并)
- HDU - 3308 - LCIS (线段树 - 区间合并)
- HDU 3308 LCIS(线段树区间合并)
- HDU 3308 LCIS(线段树区间合并 单点更新)
- HDU 3308 LCIS (线段树区间合并)
- hdu 3308 LCIS(线段树区间合并)
- HDU 3308 - LCIS(线段树+区间合并)
- hdu 3308 LCIS (线段树区间合并)
- HDU 3308 LCIS(线段树的区间合并)
- HDU OJ 3308 LCIS 【线段树之区间合并】
- 整理下 Intent 中文API 19
- 2016年终总结及规划
- JAVAの日记
- 关于Java中Process类和Runtime.exec()的一些使用
- Android 中assets的作用和用法
- hdu 3308 LCIS (线段树区间合并)
- CustomGridListControl++Shieory
- C8-2 圆的周长和面积
- noi-8183-画矩形
- [杜教筛 约数和前缀和] 51Nod 1220 约数之和
- Codeforces 463C Gargari and Bishops 贪心+规律
- wildfly10配置数据源
- Angular.js 之 如何使用ng-touch
- Haskell语言学习笔记(3)map, filter, fold