【HDU

来源:互联网 发布:开发上位机界面软件 编辑:程序博客网 时间:2024/05/22 04:10

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
没思路,Orz 一下大佬们。
解看代码吧。
代码

#include<bits/stdc++.h>using namespace std;#define  LL long long#define fread() freopen("in.txt","r",stdin)#define fwrite() freopen("out.txt","w",stdout)#define CLOSE() ios_base::sync_with_stdio(false)const int MAXN = 1e5+10;const int MAXM = 1e6;const int mod = 1e9+7;const int inf = 0x3f3f3f3f;struct Tree{    int l, r, len;//区间左右端点 和 长度      int lv, rv;//区间左端点的值  右端点的值      int lsum, rsum;//以区间左端点为起点的最长递增序列长度 以区间右端点为终点的最长递增序列长度      int sum;//区间 最长递增序列长度 }tree[MAXN<<2];void Up(int o){    tree[o].lv=tree[o<<1].lv;    tree[o].rv=tree[o<<1|1].rv;    tree[o].lsum=tree[o<<1].lsum;    tree[o].rsum=tree[o<<1|1].rsum;    tree[o].sum=max(tree[o<<1].sum,tree[o<<1|1].sum);    if(tree[o<<1].rv<tree[o<<1|1].lv){        if(tree[o<<1].lsum==tree[o<<1].len)   //左半区间完全容纳最长递增序列 向右延伸            tree[o].lsum+=tree[o<<1|1].lsum;        if(tree[o<<1|1].rsum==tree[o<<1|1].len) //右半区间完全容纳最长递增序列 向左延伸              tree[o].rsum+=tree[o<<1].rsum;        tree[o].sum=max(tree[o].sum,max(tree[o].lsum,tree[o].rsum));  //更新         tree[o].sum=max(tree[o].sum,tree[o<<1].rsum+tree[o<<1|1].lsum);    }}void Build(int o,int le,int ri){    tree[o].l=le;tree[o].r=ri;tree[o].len=ri-le+1;    if(le==ri){        int val;scanf("%d",&val);        tree[o].lv=tree[o].rv=val;        tree[o].lsum=tree[o].rsum=tree[o].sum=1;        return ;    }    int mid=(tree[o].l+tree[o].r)>>1;    Build(o<<1,le,mid);    Build(o<<1|1,mid+1,ri);    Up(o);}void UpDate(int o,int pos,int val){    if(tree[o].l==tree[o].r){        tree[o].lv=tree[o].rv=val;        return ;    }    int mid=(tree[o].l+tree[o].r)>>1;    if(pos<=mid) UpDate(o<<1,pos,val);    else UpDate(o<<1|1,pos,val);    Up(o);}int Query(int o,int le,int ri){    if(le<=tree[o].l&&tree[o].r<=ri) {        return tree[o].sum;    }    int mid=(tree[o].l+tree[o].r)>>1;    if(ri<=mid) return Query(o<<1,le,ri);    else if(le>mid) return Query(o<<1|1,le,ri);    else {        int a=Query(o<<1,le,mid);        int b=Query(o<<1|1,mid+1,ri);        int ans=max(a,b);        if(tree[o<<1].rv<tree[o<<1|1].lv) {  //  不在区间里的话,会查询两个部分的最大值,        //但是其实这两个部分是连着的,所以有的这里的代码             ans=max(ans,min(tree[o<<1].rsum,mid-le+1)+min(tree[o<<1|1].lsum,ri-mid));        }        return ans;    } }int main(){    CLOSE();//  fread();//  fwrite();    int T;scanf("%d",&T);    while(T--){        int n,q;        scanf("%d%d",&n,&q);        Build(1,0,n-1);        char op[5];        while(q--){            int a,b;            scanf("%s%d%d",op,&a,&b);            if(op[0]=='U') UpDate(1,a,b);            else printf("%d\n",Query(1,a,b));        }    }    return 0;}