zoukankan      html  css  js  c++  java
  • 【POJ3667】Hotel

    一道线段树区间合并的问题。

    我们需要每次用线段树查找是否存在一个连续的为0的且长度不短与x的子序列、查找完成后需要返回这个子序列的左端点,并且将该子序列全部赋值为1,还需要用线段树完成对一个子序列的赋值。

    我们在线段树的每一个节点上维护四个量:tag,sum,l,r分别表示该区间的值(0表示全部为0、1表示全部为1、-1表示其他情况)、这个区间最大连续为0的子序列(下文简称合法序列)的长度、以这个区间左端点为起点的合法序列的长度、以这个区间右端点为起点的合法序列的长度、这个区间的合法序列的长度。

    关于这四个量的维护,可以参阅这里

    我们重点讨论一下查询操作。设查询的长度为x,如果整个序列的sum小于x则无解,直接输出0即可。否则,如果当前区间的左子区间的合法序列的长度大于等于x,那么递归左子区间,在左子区间中找答案。如果答案区间横跨左右子区间,我们特殊处理。剩余的情况,我们到其右子区间寻找答案即可。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 struct node {
     7     int l,r,sum,tag;
     8 }a[50010<<2];
     9 int n,m;
    10 inline void pushup(int now,int l,int r) {
    11     a[now].l=a[now<<1].tag==0?a[now<<1].l+a[now<<1|1].l:a[now<<1].l;
    12     a[now].r=a[now<<1|1].tag==0?a[now<<1|1].r+a[now<<1].r:a[now<<1|1].r;
    13     a[now].sum=max(a[now<<1].r+a[now<<1|1].l,max(a[now<<1].sum,a[now<<1|1].sum));
    14     if(a[now].sum==0) a[now].tag=1;
    15     else if(a[now].sum==r-l+1) a[now].tag=0;
    16     else a[now].tag=-1;
    17 }
    18 inline void pushdown(int now,int l,int r) {
    19     if(a[now].tag==-1) return ;
    20     a[now<<1].tag=a[now<<1|1].tag=a[now].tag;
    21     a[now<<1].l=a[now<<1].r=a[now<<1].sum=a[now<<1].tag==0?((r-l+1)-(r-l+1>>1)):0;
    22     a[now<<1|1].l=a[now<<1|1].r=a[now<<1|1].sum=a[now<<1|1].tag==0?(r-l+1>>1):0;
    23 }
    24 inline void build(int now,int l,int r) {
    25     if(l==r) {
    26         a[now].tag=0;
    27         a[now].l=a[now].r=a[now].sum=1;
    28         return ;
    29     }
    30     int mid=l+r>>1;
    31     build(now<<1,l,mid);
    32     build(now<<1|1,mid+1,r);
    33     pushup(now,l,r);
    34 }
    35 void updata(int now,int l,int r,int x,int y,int val) {
    36     if(x<=l&&r<=y) {
    37         a[now].tag=val;
    38         a[now].l=a[now].r=a[now].sum=val==0?(r-l+1):0;
    39         return ;
    40     }
    41     int mid=l+r>>1;
    42     pushdown(now,l,r);
    43     if(x<=mid) updata(now<<1,l,mid,x,y,val);
    44     if(y>mid) updata(now<<1|1,mid+1,r,x,y,val);
    45     pushup(now,l,r);
    46 }
    47 int query(int now,int l,int r,int x) {
    48     if(l==r) return l;
    49     pushdown(now,l,r);
    50     int mid=l+r>>1;
    51     if(a[now<<1].sum>=x) return query(now<<1,l,mid,x);
    52     else if(a[now<<1].r+a[now<<1|1].l>=x) return mid-a[now<<1].r+1;
    53     return query(now<<1|1,mid+1,r,x);
    54 }
    55 int main() {
    56     scanf("%d%d",&n,&m);
    57     build(1,1,n);
    58     while(m--) {
    59         int op,x,y;
    60         scanf("%d",&op);
    61         if(op==1) {
    62             scanf("%d",&x);
    63             if(a[1].sum<x) {
    64                 puts("0");
    65                 continue ;
    66             }
    67             int ans=query(1,1,n,x);
    68             updata(1,1,n,ans,ans+x-1,1);
    69             printf("%d
    ",ans);
    70         }
    71         else {
    72             scanf("%d%d",&x,&y);
    73             updata(1,1,n,x,x+y-1,0);
    74         }
    75     }
    76     return 0;
    77 }
    AC Code
  • 相关阅读:
    视图、触发器、事物、存储过程、函数、流程控制
    pymysql
    单表查询与多表查询
    多线程学习(第三天)线程间通信
    多线程学习(第二天)Java内存模型
    多线程学习(第一天)java语言的线程
    springboot集成es7(基于high level client)
    elasticSearch(六)--全文搜索
    elasticSearch(五)--排序
    elasticSearch(四)--结构化查询
  • 原文地址:https://www.cnblogs.com/shl-blog/p/10922358.html
Copyright © 2011-2022 走看看