HDU1540--线段树(最长连续区间)

这个题目好像不是很难,可是我想了很久,还超时了。。我用的是普通线段树和二分,第一次用二分超时啊啊啊啊啊

好,让我们言归正传。(参考别的大佬的做法,贼6)

看到这个题目之后,能够想到它是为了求包含一个点的最大连续区间。那么多的区间,应该是要用线段树来做。

可以想得到,查询的时候,是从这个点展开,判断左右是否连续。

首先,我们用递归查询到这个点,或者说是包含这个点的连续区间,假设它是一个左子树,那我们就要加上它相邻的右子树的从左边开始的连续区间,如果它是右子树,那么就按相反。

这样的话,我们不如就建立两个数组,一个是从左边开始累加区间长度的数组(lsum[]),一个是从右边开始累加区间长度的数组(rsum[]),然后建树,更新节点,查询。

还要提一点,由于题目中有一个什么重建,emmm,就是先进后出的栈嘛,所以我们这里就可以用到c++中的一个stack容器

有这几个常用的操作吧:

stack s;

1.入栈:如s.push(x);

2.出栈:如 s.pop().注意:出栈操作只是删除栈顶的元素,并不返回该元素。

3.访问栈顶:如s.top();

4.判断栈空:如s.empty().当栈空时返回true。

5.访问栈中的元素个数,如s.size();

贴代码:

#include"cstdio"
#include"stack"
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 50010

int lsum[4*maxn],rsum[4*maxn],flag;
void Build(int l,int r,int rt) {
    lsum[rt] = rsum[rt] = r-l+1;
    if (l == r) return;
    int m = (l+r) >> 1;
    Build(lson);
    Build(rson);
}
void Pushup(int rt,int m) {
    lsum[rt] = lsum[rt<<1];
    rsum[rt] = rsum[rt<<1|1];
    if (lsum[rt] == m - (m>>1)) lsum[rt] += lsum[rt<<1|1];//yi cuo
    if (rsum[rt] == m>>1) rsum[rt] += rsum[rt<<1];
}
void Updata(int p,int x,int l,int r,int rt) {
    if (l == r) {
        lsum[rt] = rsum[rt] = x;
        return;
    }
    int m = (l+r) >> 1;
    if (p <= m) Updata(p,x,lson); else Updata(p,x,rson);
    Pushup(rt,r-l+1);
}
int Query(int p,int l,int r,int rt) {
    if (rsum[rt] >= r-p+1) {
        flag = 1;
        return rsum[rt];
    }
    if (lsum[rt] >= p-l+1) {
        flag = 1;
        return lsum[rt];
    }
    if (l == r) return 0;
    int m = (l+r) >> 1, t = 0;
    if (p > m) {
        t = Query(p,rson);
        if (flag) {
            flag = 0;
            t += rsum[rt<<1];
        }
    } else {
        t = Query(p,lson);
        if (flag) {
            flag = 0;
            t += lsum[rt<<1|1];
        }
    }
    return t;
}
int main() {
    int n,m;
//    freopen("1.in","r",stdin);
    while(~scanf("%d%d",&n,&m)) {
        Build(1,n,1);
        char cmd[2];
        stack sta;
        for (int i = 0;i < m;i ++) {
            scanf("%s",cmd);
            if (cmd[0] == 'D') {
                int x;
                scanf("%d",&x);
                sta.push(x);
                Updata(sta.top(),0,1,n,1);
            } else
            if (cmd[0] == 'Q') {
                int x;
                flag = 0;
                scanf("%d",&x);
                printf("%d\n",Query(x,1,n,1));
            } else {
                Updata(sta.top(),1,1,n,1);
                sta.pop();
            }
        }
    }
    return 0;
}




你可能感兴趣的:(算法)