HDU 3308 LCIS(线段树+区间合并+最长递增连续子串)
2017-10-01 16:07
477 查看
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.
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int MAXN = 100100;
int val[MAXN];
int lsum[MAXN << 2], rsum[MAXN << 2], msum[MAXN << 2];
void PushUp(int l, int r,int rt)
{
int m = (l + r)>>1;
msum[rt] = max(msum[rt
4000
<<1], msum[rt<<1|1]); //更新msum
if (val[m] < val[m + 1]) msum[rt] = max(msum[rt], rsum[rt<<1] + lsum[rt<<1|1]);//满足条件左右子树可以合并
lsum[rt] = lsum[rt<<1]; //更新lsum
if (lsum[rt] == m - l + 1 && val[m] < val[m + 1]) lsum[rt] += lsum[rt<<1|1];//左子树是满的,满足条件左右子树可以合并
rsum[rt] = rsum[rt<<1|1]; //更新rsum
if (rsum[rt] == r - m && val[m] < val[m + 1]) rsum[rt] += rsum[rt<<1];//右子树是满的,满足条件左右子树可以合并
}
//建立线段树且更新所有节点
void build( int l, int r,int rt)
{
if (l == r)
{
msum[rt] = rsum[rt] = lsum[rt] = 1;
return;
}
int m = (r + l) >> 1;
build(lson);
build(rson);
PushUp(l, r,rt);
}
//将q号元素的值置换为v
void update(int q, int v, int l, int r,int rt)
{
if (l == r)
{
val[l] = v;
msum[rt] = rsum[rt] = lsum[rt] = 1;
return;
}
int m = (r + l)>>1;
if (q <= m) update(q, v, lson);
else update(q, v, rson);
PushUp(l, r,rt);
}
int query(int L, int R, int l, int r, int rt)
{
//在区间里
if (L <= l && r <= R)
{
return msum[rt];
}
int m = (l + r) >> 1;
if (R <= m) return query(L, R, lson);//在左子树
else if (m<L) return query(L, R, rson);//在右子树
//在左的右子树和右的左子树
int res = max(query(L, R, lson), query(L, R, rson));
int lsumx = min(R - m, lsum[rt<<1|1]);//[m+1,R]与[m+1,r]相交部分
int rsumx = min(m - L + 1, rsum[rt<<1]);//[L,m]与[l,m]相交部分
if (val[m]<val[m + 1]) res = max(res, lsumx + rsumx);
return res;
}
int main()
{
int T, n, m;
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++)
scanf("%d", &val[i]);
build(0,n-1,1);
while (m--)
{
char str[10];
int x, y;
scanf("%s%d%d", str, &x, &y);
if (str[0] == 'U')
update(x, y, 0, n - 1, 1);
else if (str[0] == 'Q')
printf("%d\n", query(x, y, 0, n - 1, 1));
}
}
return 0;
}
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.
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int MAXN = 100100;
int val[MAXN];
int lsum[MAXN << 2], rsum[MAXN << 2], msum[MAXN << 2];
void PushUp(int l, int r,int rt)
{
int m = (l + r)>>1;
msum[rt] = max(msum[rt
4000
<<1], msum[rt<<1|1]); //更新msum
if (val[m] < val[m + 1]) msum[rt] = max(msum[rt], rsum[rt<<1] + lsum[rt<<1|1]);//满足条件左右子树可以合并
lsum[rt] = lsum[rt<<1]; //更新lsum
if (lsum[rt] == m - l + 1 && val[m] < val[m + 1]) lsum[rt] += lsum[rt<<1|1];//左子树是满的,满足条件左右子树可以合并
rsum[rt] = rsum[rt<<1|1]; //更新rsum
if (rsum[rt] == r - m && val[m] < val[m + 1]) rsum[rt] += rsum[rt<<1];//右子树是满的,满足条件左右子树可以合并
}
//建立线段树且更新所有节点
void build( int l, int r,int rt)
{
if (l == r)
{
msum[rt] = rsum[rt] = lsum[rt] = 1;
return;
}
int m = (r + l) >> 1;
build(lson);
build(rson);
PushUp(l, r,rt);
}
//将q号元素的值置换为v
void update(int q, int v, int l, int r,int rt)
{
if (l == r)
{
val[l] = v;
msum[rt] = rsum[rt] = lsum[rt] = 1;
return;
}
int m = (r + l)>>1;
if (q <= m) update(q, v, lson);
else update(q, v, rson);
PushUp(l, r,rt);
}
int query(int L, int R, int l, int r, int rt)
{
//在区间里
if (L <= l && r <= R)
{
return msum[rt];
}
int m = (l + r) >> 1;
if (R <= m) return query(L, R, lson);//在左子树
else if (m<L) return query(L, R, rson);//在右子树
//在左的右子树和右的左子树
int res = max(query(L, R, lson), query(L, R, rson));
int lsumx = min(R - m, lsum[rt<<1|1]);//[m+1,R]与[m+1,r]相交部分
int rsumx = min(m - L + 1, rsum[rt<<1]);//[L,m]与[l,m]相交部分
if (val[m]<val[m + 1]) res = max(res, lsumx + rsumx);
return res;
}
int main()
{
int T, n, m;
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++)
scanf("%d", &val[i]);
build(0,n-1,1);
while (m--)
{
char str[10];
int x, y;
scanf("%s%d%d", str, &x, &y);
if (str[0] == 'U')
update(x, y, 0, n - 1, 1);
else if (str[0] == 'Q')
printf("%d\n", query(x, y, 0, n - 1, 1));
}
}
return 0;
}
相关文章推荐
- HDU 3308——LCIS(线段树,区间合并,最长连续递增子序列)
- 线段树区间合并+最长连续递增子序列——HDU 3308
- HDU 3308 LCIS(最长连续上升子序列)(线段树区间合并)
- hdu 3308 LCIS 最大连续递增字串长 线段树区间合并
- HDU 3308 LCIS 最长连续递增序列+数据结构+线段树+单点更新
- hdu 3308 LCIS(线段树 最长连续递增)
- HDU 3308 LCIS 最长上升字串(线段树区间合并)
- hdoj 3308 LCIS 【线段树单点更新 + 区间合并】【求解最长递增序列 的长度】
- HDU 3308 LCIS(线段树区间合并)
- (简单) HDU 3308 LCIS,线段树+区间合并。
- HDU - 3308 - LCIS (线段树 - 区间合并)
- HDU 3308 LCIS(线段树:单点更新,求最大连续子串)
- HDU 3308 LCIS(线段树,连续递增子)
- hdu 3308 LCIS(线段树区间合并)
- hdu 3308 线段树-区间连续最长上升子序列
- HDU 3308 LCIS (线段树合并区间)
- HDU 3308 LCIS 线段树 区间合并 入门题
- hdu--3308 LCIS(线段树+区间合并)
- hdu 3308 LCIS(线段树区间合并)
- HDU 3308【线段树-query:区间最长单调上升序列,update:结点更新,区间合并】