对应HDU题目:点击打开链接
Time Limit: 2000MS | Memory Limit: 32768KB | 64bit IO Format: %I64d & %I64u |
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].
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<=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).
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).
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
Source
题意:给出n个数,m个询问,每个询问包含 (c,a,b) ,c=U时,把下标为a的值改为b,c=Q时,求[a,b]之间的最长连续递增子序列,并输出
思路:线段树区间合并;
对于一段区间[l,r],mid为中间值,要求[a,b]之间(其中a,b在[l,r]内)的lcis,则最长连续递增子序列要么在mid左边,要么在mid右边,要么是mid左右两边都有。所以线段树区间维护的就是3个数组,一个是该区间的lcis,用lcis[rt]表示,一个是从区间左边界数起连续递增序列的个数llcis[rt],一个是从区间右边界数起连续递减序列的个数rlcis[rt]。
试了下两种╮(╯_╰)╭
[0,9] 和 [0,9]
[0,4] [4,9] [0,4] [5,9]
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#define ms(x,y) memset(x,y,sizeof(x))
#define eps 1e-6
const int MAXN=400000+10;
const int INF=1<<30;
using namespace std;
int value[MAXN/4];
int lcis[MAXN];
int llcis[MAXN];
int rlcis[MAXN];
void up(int rt, int mid, int len)
{
llcis[rt] = llcis[rt<<1];
rlcis[rt] = rlcis[rt<<1|1];
lcis[rt] = max(lcis[rt<<1], lcis[rt<<1|1]);
if( value[mid+1] > value[mid] ){
if(llcis[rt] == len-(len>>1)) llcis[rt] += llcis[rt<<1|1];
if(rlcis[rt] == (len>>1)) rlcis[rt] += rlcis[rt<<1];
lcis[rt] = max(rlcis[rt<<1] + llcis[rt<<1|1], lcis[rt]);
}
}
void update_change(int rt, int left, int right, int pos)
{
if(left == right) return;
if(right - left == 1){
if(value[left] < value[right]){
lcis[rt] = 2;
llcis[rt] = 2;
rlcis[rt] = 2;
}
else{
lcis[rt] = 1;
llcis[rt] = 1;
rlcis[rt] = 1;
}
return;
}
int mid=(left+right)>>1;
if(mid >= pos) update_change(rt<<1, left, mid, pos);
else update_change(rt<<1|1, mid+1, right, pos);
up(rt, mid, right-left+1);
}
int query(int rt, int left, int right, int l, int r)
{
if(l == left && right == r) return lcis[rt];
int mid=(left + right)>>1;
if(mid >= r) return query(rt<<1, left, mid, l, r);
else if(mid < l) return query(rt<<1|1, mid+1, right, l, r);
else{
int len1=query(rt<<1, left, mid, l, mid);
int len2=query(rt<<1|1, mid+1, right, mid+1, r);
int len3=0;
if(value[mid+1] > value[mid]) len3=min(rlcis[rt<<1], mid-l+1) + min(llcis[rt<<1|1], r-mid);
return max(len1, max(len2,len3));
}
}
void Initialize()
{
for(int i=0; i<MAXN; i++){
lcis[i]=1;
llcis[i]=1;
rlcis[i]=1;
}
}
int main()
{
//freopen("in.txt","r",stdin);
int T;
scanf("%d", &T);
while(T--)
{
Initialize();
char op;
int n,m;
int a,b;
scanf("%d%d", &n,&m);
for(int i=0; i<n; i++){
scanf("%d", &value[i]);
update_change(1,0,n-1,i);
}
while(m--)
{
scanf(" %c%d%d", &op,&a,&b);
if(op == 'U'){
value[a]=b;
update_change(1,0,n-1,a);
}
else{
if(b - a == 1 || b - a == 0){//求相邻的两个数或求一个数
if(value[a] >= value[b]) printf("1\n");
else printf("2\n");
}
else printf("%d\n", query(1,0,n-1,a,b));//求三个数以上
}
}
}
return 0;
}
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#define ms(x,y) memset(x,y,sizeof(x))
#define eps 1e-6
const int MAXN=400000+10;
const int INF=1<<30;
using namespace std;
int value[MAXN];
int lcis[MAXN];
int llcis[MAXN];
int rlcis[MAXN];
void up(int rt, int len)
{
int llen,rlen;
llen=rlen=(len>>1) + 1;
if((len&1) == 0) llen--;
llcis[rt] = llcis[rt<<1];
rlcis[rt] = rlcis[rt<<1|1];
if(llcis[rt] == llen) llcis[rt] += llcis[rt<<1|1] - 1;
if(rlcis[rt] == rlen) rlcis[rt] += rlcis[rt<<1] - 1;
lcis[rt] = max(rlcis[rt<<1] + llcis[rt<<1|1] - 1, max(lcis[rt<<1], lcis[rt<<1|1]));
}
void update_change(int rt, int left, int right, int pos)
{
if(right - left ==1){
int lval=value[left];
int rval=value[right];
if(lval < rval){
lcis[rt] = 2;
llcis[rt] = 2;
rlcis[rt] = 2;
}
else{
lcis[rt] = 1;
llcis[rt] = 1;
rlcis[rt] = 1;
}
return;
}
int mid=(left+right)>>1;
if(mid > pos) update_change(rt<<1, left, mid, pos);
else if(mid < pos) update_change(rt<<1|1, mid, right, pos);
else{
update_change(rt<<1, left, mid, pos);
update_change(rt<<1|1, mid, right, pos);
}
up(rt, right-left+1);
}
int query(int rt, int left, int right, int l, int r)
{
if(l == left && right == r) return lcis[rt];
int mid=(left + right)>>1;
if(mid >= r) return query(rt<<1, left, mid, l, r);
else if(mid <= l) return query(rt<<1|1, mid, right, l, r);
else{
int len1=query(rt<<1, left, mid, l, mid);
int len2=query(rt<<1|1, mid, right, mid, r);
int len3=min(rlcis[rt<<1], mid-l+1) + min(llcis[rt<<1|1], r-mid+1) - 1;
return max(len1, max(len2,len3));
}
}
void Initialize()
{
for(int i=0; i<MAXN; i++){
lcis[i]=1;
llcis[i]=1;
rlcis[i]=1;
value[i]=0;
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("c:\\Users\\Administrator\\Desktop\\out.txt","w",stdout);
int T;
scanf("%d", &T);
while(T--)
{
Initialize();
char op;
int n,m;
int a,b;
scanf("%d%d", &n,&m);
for(int i=0; i<n; i++){
scanf("%d", &value[i]);
update_change(1,0,n-1,i);
}
#if 0
for(int j=1; j<=31; j++){
cout<<j<<": "<<lcis[j]<<endl;
cout<<" "<<llcis[j]<<endl;
cout<<" "<<rlcis[j]<<endl;
}
cout<<endl;
#endif
while(m--)
{
scanf(" %c%d%d", &op,&a,&b);
//cin>>op>>a>>b;
if(op == 'U'){
value[a]=b;
update_change(1,0,n-1,a);
}
else{
if(b - a == 1 || b - a == 0){
if(value[a] >= value[b]) printf("1\n");
else printf("2\n");
}
else printf("%d\n", query(1,0,n-1,a,b));
}
}
}
return 0;
}