hdu1540线段树

https://vjudge.net/contest/66989#problem/I

#include<iostream>
#include<cstdio>
#include<cmath>
#include<stack>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
const int maxn=50010;
LL value[maxn<<2],ll[maxn<<2],rl[maxn<<2],ml[maxn<<2];//ll是rt左边连续为1的个数,rl是右边,ml是左右两边
void btree(int l,int r,int rt)
{
    ll[rt]=rl[rt]=ml[rt]=r-l+1;//初始化全部为1
    if(l==r)return ;
    int m=(l+r)>>1;
    btree(ls);
    btree(rs);
}
void update(int k,int flag,int l,int r,int rt)//flag=0代表摧毁,=1代表重建
{
    if(l==r)
    {
        ll[rt]=rl[rt]=ml[rt]=flag;//更新叶子节点的值
        return ;
    }
    int m=(l+r)>>1;
    if(k<=m)update(k,flag,ls);
    else update(k,flag,rs);
    if((ll[rt]=ll[rt<<1])==m-l+1)ll[rt]+=ll[rt<<1|1];//更新左边
    if((rl[rt]=rl[rt<<1|1])==r-m)rl[rt]+=rl[rt<<1];
    ml[rt]=max(max(ml[rt<<1],ml[rt<<1|1]),rl[rt<<1]+ll[rt<<1|1]);//更新ml的值
}
LL query(int k,int l,int r,int rt)
{
    if(l==r||ml[rt]==r-l+1||ml[rt]==0)return ml[rt];
    int m=(l+r)>>1;
    if(k<=m)//查询点在左侧
    {
        if(k>m-rl[rt<<1])return query(k,ls)+query(m+1,rs);
        else return query(k,ls);
    }
    else
    {
        if(k<m+1+ll[rt<<1|1])return query(m,ls)+query(k,rs);
        else return query(k,rs);
    }
}
int main()
{
    int n,m,k;
    while(~scanf("%d%d",&n,&m)){
        stack<int>a;
        btree(1,n,1);
        while(m--){
            char op[2];
            scanf("%s",&op);
            if(op[0]!='R')
            {
                scanf("%d",&k);
                if(op[0]=='D')
                {
                    a.push(k);
                    update(k,0,1,n,1);
                }
                if(op[0]=='Q')printf("%lld
",query(k,1,n,1));
            }
            else
            {
                update(a.top(),1,1,n,1);
                a.pop();
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/acjiumeng/p/6501618.html