您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: