• [BZOJ4592][SHOI2015]脑洞治疗仪(线段树)


    线段树基础操作题,唯一需要思考下的是将区间的前k个0覆盖为1。

    线段树上二分,先递归到左子树覆盖,回溯时返回还剩多少个0未被覆盖,在根据这个信息递归到右子树。注意特判k=0的情况。

    要维护的信息有:区间左边最长0连续段,右边最长0连续段,区间整体最长0连续段,区间内1的个数,以及一个记录是否被区间覆盖的懒惰标记。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #define ls (x<<1)
     4 #define rs (ls|1)
     5 #define lson ls,L,mid
     6 #define rson rs,mid+1,R
     7 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
     8 using namespace std;
     9 
    10 const int N=200010;
    11 int n,m,op,l,r,l1,r1,l2,r2,mx[N<<2],mxl[N<<2],mxr[N<<2],cnt[N<<2],tag[N<<2];
    12 
    13 void build(int x,int L,int R){
    14     int mid=(L+R)>>1;
    15     tag[x]=-1; cnt[x]=R-L+1;
    16     if (L==R) return;
    17     build(lson); build(rson);
    18 }
    19 
    20 void upd(int x,int L,int R){
    21     int mid=(L+R)>>1;
    22     mxl[x]=mxl[ls]+(mxl[ls]==mid-L+1 ? mxl[rs] : 0);
    23     mxr[x]=mxr[rs]+(mxr[rs]==R-mid ? mxr[ls] : 0);
    24     mx[x]=max(max(mx[ls],mx[rs]),mxr[ls]+mxl[rs]);
    25     cnt[x]=cnt[ls]+cnt[rs];
    26 }
    27 
    28 void put(int x,int L,int R,int k){
    29     if (!k) mxl[x]=mxr[x]=mx[x]=R-L+1,cnt[x]=0,tag[x]=k;
    30         else mxl[x]=mxr[x]=mx[x]=0,cnt[x]=R-L+1,tag[x]=k;
    31 }
    32 
    33 void push(int x,int L,int R){
    34     int mid=(L+R)>>1;
    35     if (~tag[x]) put(ls,L,mid,tag[x]),put(rs,mid+1,R,tag[x]),tag[x]=-1;
    36 }
    37 
    38 void mdf(int x,int L,int R,int l,int r,int k){
    39     if (L==l && r==R){ put(x,L,R,k); return; }
    40     int mid=(L+R)>>1; push(x,L,R);
    41     if (r<=mid) mdf(lson,l,r,k);
    42     else if (l>mid) mdf(rson,l,r,k);
    43         else mdf(lson,l,mid,k),mdf(rson,mid+1,r,k);
    44     upd(x,L,R);
    45 }
    46 
    47 int que(int x,int L,int R,int l,int r){
    48     if (L==l && r==R) return cnt[x];
    49     int mid=(L+R)>>1; push(x,L,R);
    50     if (r<=mid) return que(lson,l,r);
    51     else if (l>mid) return que(rson,l,r);
    52         else return que(lson,l,mid)+que(rson,mid+1,r);
    53 }
    54 
    55 int paint(int x,int L,int R,int l,int r,int k){
    56     if (!k) return 0;
    57     if (L==l && r==R && R-L+1-cnt[x]<=k){ k-=R-L+1-cnt[x]; put(x,L,R,1); return k; }
    58     int mid=(L+R)>>1; push(x,L,R);
    59     if (r<=mid) k=paint(lson,l,r,k);
    60     else if (l>mid) k=paint(rson,l,r,k);
    61         else{
    62             int t=paint(lson,l,mid,k);
    63             if (t) k=paint(rson,mid+1,r,t); else k=0;
    64         }
    65     upd(x,L,R); return k;
    66 }
    67 
    68 int get(int x,int L,int R,int l,int r){
    69     if (L==l && r==R) return mx[x];
    70     int mid=(L+R)>>1; push(x,L,R);
    71     if (r<=mid) return get(lson,l,r);
    72     else if (l>mid) return get(rson,l,r);
    73         else return max(max(get(lson,l,mid),get(rson,mid+1,r)),min(mxr[ls],mid-l+1)+min(mxl[rs],r-mid));
    74 }
    75 
    76 int main(){
    77     freopen("bzoj4592.in","r",stdin);
    78     freopen("bzoj4592.out","w",stdout);
    79     scanf("%d%d",&n,&m); build(1,1,n);
    80     rep(i,1,m){
    81         scanf("%d",&op);
    82         if (op==0) scanf("%d%d",&l,&r),mdf(1,1,n,l,r,0);
    83         if (op==1){
    84             scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
    85             int t=que(1,1,n,l1,r1); mdf(1,1,n,l1,r1,0);
    86             paint(1,1,n,l2,r2,t);
    87         }
    88         if (op==2) scanf("%d%d",&l,&r),printf("%d
    ",get(1,1,n,l,r));
    89         //rep(i,1,n) printf("%d ",que(1,1,n,i,i)); puts("");
    90     }
    91     return 0;
    92 }
  • 相关阅读:
    Spring MVC 迁移项目搭建运行
    linux 安装 nginx
    linux 安装 redis
    linux 安装 jdk
    存储过程之游标插入数据
    存储过程之基础语法
    AES加密解密,自定义加密规则记录
    idea破解记录
    Mysql-explain之Using temporary和Using filesort解决方案
    C#多线程学习笔记(朝夕eleven) Task启动方式、Task阻塞、Task.Delay()、多线程异常处理、任务取消、多线程的临时变量、共享数据的lock、Task返回值
  • 原文地址:https://www.cnblogs.com/HocRiser/p/10090680.html
Copyright © 2020-2023  润新知