LCIS HDU - 3308 (线段树区间合并)

时间:2024-11-15 10:36:19

LCIS HDU - 3308

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]. 

InputT in the first line, indicating the case number. 
Each case starts with two integers n , m(0<n,m<=10 5). 
The next line has n integers(0<=val<=10 5). 
The next m lines each has an operation: 
U A B(0<=A,n , 0<=B=10 5
OR 
Q A B(0<=A<=B< n). 
OutputFor 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<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define mem(a,x) memset(a,x,sizeof(a))
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid + 1,r
#define P pair<int,int>
#define ull unsigned long long
using namespace std;
typedef long long ll;
const int maxn = 1e5 + ;
const int inf = 0x3f3f3f3f; struct node
{
int l,r;
int left ,right ,mid;
int maxx;
}tree[maxn << ]; int n,m;
int arr[maxn]; void Pushup(int rt)
{
tree[rt].left = tree[rt << ].left;
tree[rt].right = tree[rt << |].right;
bool flag = arr[tree[rt << |].l] > arr[tree[rt << ].r]; if(tree[rt << |].right == tree[rt << |].r - tree[rt << |].l + && flag)
{
tree[rt].right += tree[rt << ].right;
}
// 合并以左端点为头的最长序列 if(tree[rt << ].left == tree[rt << ].r - tree[rt << ].l + && flag)
{
tree[rt].left += tree[rt << |].left;
}
// 合并以右端点为尾的最长序列 if(arr[tree[rt << |].l] > arr[tree[rt << ].r])
{
tree[rt].mid = tree[rt << ].right + tree[rt << |].left;
}
else
{
tree[rt].mid = max(tree[rt << ].right , tree[rt << |].left);
}
tree[rt].mid = max(tree[rt].mid , max(tree[rt << ].mid,tree[rt << |].mid));
// 获得区间内的最长序列:可能由子区间构成 也可能从子区间得到
tree[rt].maxx = max(tree[rt].mid, max(tree[rt].left , tree[rt].right));
} void build(int rt ,int l ,int r)
{
tree[rt].l = l , tree[rt].r = r;
if(l == r)
{
tree[rt].left = tree[rt].right = tree[rt].maxx = tree[rt].mid = ;
return;
}
int mid = l + r >> ;
build(lson);
build(rson);
Pushup(rt);
} void update(int rt ,int k ,int v)
{
if(tree[rt].l == k && tree[rt].r == k)
{
arr[k] = v;
tree[rt].left = tree[rt].right = tree[rt].maxx = tree[rt].mid = ;
return;
}
int mid = tree[rt].l + tree[rt].r >> ;
if(mid >= k)
{
update(rt << , k , v);
}
else
{
update(rt << | , k , v);
}
Pushup(rt);
} int query(int rt , int l ,int r)
{
if(tree[rt].l == l && tree[rt].r == r)
{
return tree[rt].maxx;
}
int mid = tree[rt].l + tree[rt].r >> ;
if(mid >= r)
{
return query(rt << , l , r);
}
else if(mid < l )
{
return query(rt << | , l , r);
}
else
{
int m = min(mid - l + , tree[rt << ].right) + min(r - mid , tree[rt << |].left);
int left = query(rt<< ,l ,mid);
int right = query(rt << | , mid + , r);
if(arr[tree[rt << ].r] < arr[tree[rt << |].l])
{
return max(m,max(left , right));
}
else
{
return max(left , right);
}
}
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
//mem(arr,0);
scanf("%d %d",&n,&m);
for(int i = ; i <= n ; ++ i)
{
scanf("%d",&arr[i]);
}
build(,,n);
while(m -- )
{
char judge;
int l,r;
scanf(" %c %d %d",&judge ,&l , &r);
if(judge == 'U')
{
update(,l + ,r);
}
else
{
printf("%d\n",query(,l + , r + ));
}
}
}
return ;
}

AC代码

一个从很久以前就开始做的梦