HDOJ 3308

LCIS

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 3056    Accepted Submission(s): 1342


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<=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
 

Author
shǎ崽
 

Source
 

Recommend
wxl
 
借用某大神的讲解:

PushUp函数和query函数是关键  ,PushUp函数向上更新时,先将lsum[rt]用

lsum[rt<<1]也就是左子区间左边开始的最大长度,如果这个区间长度刚好是l到mid之间的长度,说明区间已经穿过中点了,应该

在加上右子区间lsum[rt<<1|1]这部分,类似的可以更新rsum[rt]。对于sum[rt]应该对应rsum[rt<<1]+lsum[rt<<1|1],

sum[rt<<1],sum[rt<<1|1]三种情况中的最大值,因为满足条件的最长单调区间可以是左半部分,右半部分,或者贯穿中点。

理解了这部分那么query函数可以按照类似的思路来写,但要注意的是对于贯穿中点的判断条件是A[mid]<A[mid+1],这样才能

将两部分加起来。

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <map>
#include <string>
#include <stack>
#include <cctype>
#include <vector>
#include <queue>
#include <set>
#include <utility>

using namespace std;
//#define Online_Judge
#define outstars cout << "***********************" << endl;
#define clr(a,b) memset(a,b,sizeof(a))
#define lson l , mid  , rt << 1
#define rson mid + 1 , r , rt << 1 | 1

#define mk make_pair
#define FOR(i , x , n) for(int i = (x) ; i < (n) ; i++)
#define FORR(i , x , n) for(int i = (x) ; i <= (n) ; i++)
#define REP(i , x , n) for(int i = (x) ; i > (n) ; i--)
#define REPP(i ,x , n) for(int i = (x) ; i >= (n) ; i--)
const int MAXN = 100000 + 500;
const long long LLMAX = 0x7fffffffffffffffLL;
const long long LLMIN = 0x8000000000000000LL;
const int INF = 0x7fffffff;
const int IMIN = 0x80000000;
#define eps 1e-8
#define mod 1000000007
typedef long long LL;
const double PI = acos(-1.0);
typedef double D;
typedef pair<int , int> pi;
///#pragma comment(linker, "/STACK:102400000,102400000")
int A[MAXN] ,  sum[MAXN << 2] , lsum[MAXN << 2] , rsum[MAXN << 2] , n , T , m , a , b;
void pushup(int rt , int len , int mid)
{
    lsum[rt] = lsum[rt << 1];
    rsum[rt] = rsum[rt << 1 | 1];
    int t = 1;
    if(A[mid] < A[mid + 1])
    {
        if(lsum[rt] == len - (len >> 1))
        {
            lsum[rt] += lsum[rt << 1 | 1];
        }
        if(rsum[rt] == len >> 1)
        {
            rsum[rt] += rsum[rt << 1];
        }
        t = lsum[rt << 1| 1] + rsum[rt << 1];
    }
    sum[rt] = max(t , max(sum[rt << 1] , sum[rt << 1 | 1]));
}
void build(int l , int r , int rt)
{
    if(l == r)
    {
        sum[rt] = lsum[rt] = rsum[rt] = 1;
        return ;
    }
    int mid = (l + r) >> 1;
    build(lson);build(rson);
    pushup(rt , r - l + 1 , mid);
}
void update(int p , int l , int r, int rt)
{
    if(l == r)return ;
    int mid = (l + r) >> 1;
    if(p <= mid)update(p , lson);
    else update(p , rson);
    pushup(rt , r - l + 1 , mid);
}
int query(int L , int R , int l , int r ,int rt)
{
    if(L <= l&& r <= R)return sum[rt];
    int mid = (l + r) >> 1;
    if(l == r)return 1;
    int ans = 0;
    if(R <= mid)ans = max(ans , query(L , R , lson));
    else if (L > mid)ans = max(ans , query(L ,R , rson));
    else
    {
        ans = max(ans , query(L ,R , lson));
        ans = max(ans , query(L ,R , rson));
        int ll , rr;
        if(mid - L + 1 >= rsum[rt << 1])
        {
            ll = rsum[rt << 1];
        }
        else ll = mid - L + 1;
        if(R - mid >= lsum[rt << 1 | 1])
        {
            rr = lsum[rt << 1 | 1];
        }
        else rr = R - mid;
        ans = max(ans , max(ll , rr));
        if(A[mid] < A[mid + 1])
        {
            ans = max(ans ,ll + rr);
        }
    }
    return ans;
}
int main()
{
    //ios::sync_with_stdio(false);
    #ifdef Online_Judge
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif // Online_Judge
    cin >> T;
    while(T--)
    {
        scanf("%d%d" , &n , &m);
        FORR(i , 1 , n)scanf("%d" , &A[i]);
        build(1 , n , 1);
        char s[5];
        while(m--)
        {
            scanf("%s%d%d" , s ,&a , &b);
            if(s[0] == 'U')
            {
                A[a + 1] =  b;
                update(a + 1 , 1 , n , 1);
            }
            else
            {
                int ans = query(a + 1 , b + 1 , 1 ,n , 1);
                printf("%d\n" , ans);
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值