hdu3308 LCIS(区间求和)

来源:互联网 发布:linux下etc没有inittab 编辑:程序博客网 时间:2024/06/05 11:41


http://acm.hdu.edu.cn/showproblem.php?pid=3308

题意:给你n个数m个操作,U为更新x节点值为num,Q为查询[l,r]区间内的最长连续上升子序列的长度。


思路:更新节点属性时在普通区间求和更新的基础上加一个判断前后值大小的条件,需要注意的是查询时中值落在区间内部,在区间之间的间隔那段需要判断是否越界。判断越界是区间合并相对于其他线段树类型题的特色。这道题还有一点是我自己的问题,变量没有搞好,样例可以通过就是WA,在这里搭了我六七个WA,泪。


#include <stdio.h>#include <algorithm>#include <stdlib.h>#include <string.h>#include <iostream>using namespace std;typedef long long LL;const int N = 100010;const int INF = 1e8;struct line{    int l, r;    int ls, rs, ms;//分别代表左最大连续区间值,右最大连续区间值,整体最大连续区间值}tree[4*N];int a[N];void maintain(int i){    tree[i].ls = tree[i*2].ls;    tree[i].rs = tree[i*2+1].rs;    tree[i].ms = max(tree[i*2].ms, tree[i*2+1].ms);    int mid = (tree[i].l+tree[i].r) >> 1;    if(a[mid] < a[mid+1])    {        if(tree[i*2].ms == tree[i*2].r-tree[i*2].l+1)            tree[i].ls = tree[i*2].ms+tree[i*2+1].ls;        if(tree[i*2+1].ms == tree[i*2+1].r-tree[i*2+1].l+1)            tree[i].rs = tree[i*2+1].ms+tree[i*2].rs;        tree[i].ms = max(tree[i].ms, tree[i*2].rs+tree[i*2+1].ls);    }}void build(int i, int l, int r){    tree[i].l = l;    tree[i].r = r;    if(l == r)    {        tree[i].ls = tree[i].rs = tree[i].ms = 1;        return;    }    int mid = (l + r) >> 1;    build(i*2, l, mid);    build(i*2+1, mid+1, r);    maintain(i);}void update(int i, int x, int num){    if(tree[i].l == tree[i].r && tree[i].l == x)    {        a[tree[i].l] = num;        return;    }    int mid = (tree[i].l+tree[i].r) >> 1;    if(mid >= x) update(i*2, x, num);    else update(i*2+1, x, num);    maintain(i);}int query(int i, int l, int r){    if(tree[i].l == l && tree[i].r == r)        return tree[i].ms;    int mid = (tree[i].l+tree[i].r) >> 1;    if(mid >= r)//在左子树    {        return query(i*2, l, r);    }    else if(mid < l)    {        return query(i*2+1, l, r);    }    else    {    //    tree[i].ms = max(query(i*2, l, mid), query(i*2+1, mid+1, r));        int t=max(query(i*2, l, mid),query(i*2+1, mid+1, r));        int ans = 0, t1, t2;        if(a[mid] < a[mid+1])        {            t1 = min(tree[i*2].rs, mid-(l-1));            t2 = min(tree[i*2+1].ls, r-mid);            ans = t1+t2;        }//return max(tree[i].ms, ans);这里和上面被注释掉的是我错的地方,无意间给tree[i]赋了值,虽然对这次递归没有影响,但整体上赋的变量值不一定是最大值,因为还没有判断下一步,所以整体出现错误        return max(t, ans);    }}int main(){   // freopen("in.txt", "r", stdin);    int t, n, m, x, num, l, r;    char s[5];    scanf("%d", &t);    while(t--)    {        scanf("%d%d", &n, &m);        for(int i = 1; i <= n; i++)        {            scanf("%d", &a[i]);        }        build(1, 1, n);        for(int i = 1; i <= m; i++)        {            scanf("%s", s);            if(s[0] == 'U')            {                scanf("%d%d", &x, &num);                update(1, x+1, num);            }            else if(s[0] == 'Q')            {                scanf("%d%d", &l, &r);                printf("%d\n", query(1, l+1, r+1));            }        }    }    return 0;}


0 0