码迷,mamicode.com
首页 > 其他好文 > 详细

hdu1540 区间合并+询问某点的最大连续块

时间:2019-04-01 01:12:34      阅读:147      评论:0      收藏:0      [点我收藏+]

标签:ret   std   大小   答案   ack   c++   返回   bsp   大连   

询问操作需要搞一下

今天被区间合并降智了

/*
D a: 摧毁第a个点
Q a:询问a所在的点的块大小
R :修复最后被破坏的点
对于所有的点需要进行一次更新
更新比较容易,tag用来表示区间是否是完整的 
查询时如果pos所在的大块有tag标记,那么直接返回块的大小即可
反之,如果pos在左区间,那就到左区间里去找:
    如果pos的位置和rmx[rt<<1]相连,那么答案就是rmx[rt<<1]+lmx[rt<<1|1]
    如果不相连,那么递归到左区间里找 
如果pos在右区间,
    如果pos的位置和lmx[rt<<1|1]相连,那么答案就是rmx[rt<<1]+lmx[rt<<1|1]
    如果不相连,那么递归到右区间里找
如果 l==r并且tag==0,那么就是0 
*/
#include<bits/stdc++.h>
using namespace std;
#define maxn 50005
int n,m;
stack<int>s; 

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int tag[maxn<<2],mx[maxn<<2],lmx[maxn<<2],rmx[maxn<<2];
void pushup(int l,int r,int rt){
    lmx[rt]=lmx[rt<<1],rmx[rt]=rmx[rt<<1|1];
    mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
    int m=l+r>>1;
    if(lmx[rt<<1]==m-l+1)lmx[rt]=lmx[rt<<1]+lmx[rt<<1|1];
    if(rmx[rt<<1|1]==r-m)rmx[rt]=rmx[rt<<1]+rmx[rt<<1|1];
    mx[rt]=max(mx[rt],max(lmx[rt],rmx[rt]));
    mx[rt]=max(mx[rt],rmx[rt<<1]+lmx[rt<<1|1]);     
    
    if(mx[rt]!=r-l+1)tag[rt]=0;
    else tag[rt]=1;
}
void build(int l,int r,int rt){
    tag[rt]=1;
    if(l==r){mx[rt]=lmx[rt]=rmx[rt]=1;return;}
    int m=l+r>>1;
    build(lson);build(rson);
    pushup(l,r,rt);
}
void update(int pos,int l,int r,int rt,int val){
    if(l==r){mx[rt]=lmx[rt]=rmx[rt]=tag[rt]=val;return;}
    int m=l+r>>1;
    if(pos<=m)update(pos,lson,val);
    else update(pos,rson,val);
    pushup(l,r,rt);
}
int query(int pos,int l,int r,int rt){
    if(mx[rt]==0)return 0;
    else if(tag[rt])return mx[rt];
    int m=l+r>>1;
    if(pos<=m){
        if(pos>=m-rmx[rt<<1]+1)
            return query(pos,lson)+lmx[rt<<1|1];
        else return query(pos,lson);
    }
    else {
        if(pos<=m+lmx[rt<<1|1])
            return query(pos,rson)+rmx[rt<<1];
        else return query(pos,rson);
    }
}
int main(){
    while(cin>>n>>m){
    build(1,n,1);
    while(m--){
        char opt[10];int a;
        cin>>opt;
        if(opt[0]!=R)cin>>a;
        if(opt[0]==D)update(a,1,n,1,0),s.push(a);
        if(opt[0]==Q)cout<<query(a,1,n,1)<<\n;
        if(opt[0]==R)update(s.top(),1,n,1,1),s.pop();
    }
}
}

 

hdu1540 区间合并+询问某点的最大连续块

标签:ret   std   大小   答案   ack   c++   返回   bsp   大连   

原文地址:https://www.cnblogs.com/zsben991126/p/10634017.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!