zoukankan      html  css  js  c++  java
  • P2894 [USACO08FEB]Hotel G

    P2894 [USACO08FEB]Hotel G

    传送门:https://www.luogu.com.cn/problem/P2894

    题意:

    参考样例,第一行输入n,m ,n代表有n个房间,编号为1---n,开始都为空房,m表示以下有m行操作,以下 每行先输入一个数 i ,表示一种操作:

    若i为1,表示查询房间,再输入一个数x,表示在1--n 房间中找到长度为x的连续空房,输出连续x个房间中左端的房间号,尽量让这个房间号最小,若找不到长度为x的连续空房,输出0,并且在这x个空房间中住上人。

    若i为2,表示退房,再输入两个数 x,y 代表 房间号 x---x+y-1 退房,即让房间为空。

    日均一棵树,有益身心健康 hhhhh

    区间操作,我们用线段树来处理

    刚开始所有位置都是0

    两个操作,一个查询是否有n个连续的0,如果有,把他们再变成1

    第二个 把x到x+y-1变成0

    常规的用线段树维护和啊最值啊什么的是不行的了

    这是一道 区间合并问题 (解决一段连续区间修改,查询问题)

    然后我们想啊该如何维护起始点与最大的连续区间长度

    有三种情况

    第一种

    我们假设要找的这个连续区间是在树维护的那段区间的左边

    也就是说,是以最左边为这个连续区间的起点

    第二种

    我们假设要找的这个连续区间是在树维护的那段区间的中间

    第三种

    我们假设要找的这个连续区间是在树维护的那段区间的右边

    我们就可以用线段树维护 左端连续区间长度ls、右端连续区间长度rs,最大连续长度sum

    重点在于push_up操作

    每次push_up是从俩儿子到父亲的过程

    我们想,父亲的ls是咋来的呢

    两种情况

     第一种,是来自左儿子的全部和右儿子的ls

    第二种,仅来自左儿子的ls

    然后rs同理

     最后这种情况当然就是来自左儿子rs的和右儿子的ls啦

    因为最后的这种情况不需要保留(对他的父亲无影响),我们的sum维护的还是最大连续长度,所以sum对这三种情况取大

    最后解释一下参数叭

    struct node 
    {
        int l(区间左端点),r(区间右端点),lazy(是否被标记),ls(左端连续区间长度),rs(左端连续区间长度),sum(最大连续长度);
    }tree[maxn*4];
    build(int l(左端点),int r(右端点),int now(当前编号))
    push_up(int now(当前编号))
    push_down(int now(当前编号))
    void update(int l(区间左端点),int r(区间右端点),int now(当前编号),int tag(指令是1还是2))
    int query(int l(区间左端点),int r(区间右端点),int now(当前编号),int len(要找的连续的多长的0))


     
      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 #define ll long long
      4 #define lowbit(a) ((a)&-(a))
      5 #define clean(a,b) memset(a,b,sizeof(a))
      6 const int mod = 1e9 + 7;
      7 const int inf=0x3f3f3f3f;
      8 const int maxn = 5e4+10;
      9  
     10 int _;
     11  
     12 /////////////////////////////////////////////////////////////////////////////////////////
     13 struct node 
     14 {
     15     int l,r,lazy,ls,rs,sum;
     16 }tree[maxn*4];
     17 //维护连续的0的个数
     18 void build(int l,int r,int now)
     19 {
     20     tree[now].l=l;
     21     tree[now].r=r;
     22     tree[now].lazy=0;
     23     tree[now].ls=tree[now].rs=tree[now].sum=r+1-l;
     24     if(l==r) return ;
     25     int mid=(l+r)>>1;
     26     build(l,mid,now<<1);
     27     build(mid+1,r,now<<1|1);
     28 }
     29 void push_up(int now)
     30 {
     31     if(tree[now<<1].sum==(tree[now<<1].r-tree[now<<1].l+1))
     32     {
     33         tree[now].ls=(tree[now<<1].r-tree[now<<1].l+1)+tree[now<<1|1].ls;
     34     }
     35     else 
     36     {
     37         tree[now].ls=tree[now<<1].ls;
     38     }
     39     if(tree[now<<1|1].sum==(tree[now<<1|1].r-tree[now<<1|1].l+1))
     40     {
     41         tree[now].rs=(tree[now<<1|1].r-tree[now<<1|1].l+1)+tree[now<<1].rs;
     42     }
     43     else 
     44     {
     45         tree[now].rs=tree[now<<1|1].rs;
     46     }
     47     tree[now].sum=max(tree[now<<1].rs+tree[now<<1|1].ls,max(tree[now<<1].sum,tree[now<<1|1].sum));
     48 }
     49 void push_down(int now)
     50 {
     51     if(tree[now].lazy==0) return ;
     52     else if(tree[now].lazy==1) 
     53     {
     54         tree[now<<1].sum=tree[now<<1].ls=tree[now<<1].rs=0;
     55         tree[now<<1|1].sum=tree[now<<1|1].ls=tree[now<<1|1].rs=0;
     56         tree[now<<1].lazy=tree[now<<1|1].lazy=1;
     57     }
     58     else if(tree[now].lazy==2)
     59     {
     60         tree[now<<1].sum=tree[now<<1].ls=tree[now<<1].rs=tree[now<<1].r-tree[now<<1].l+1;
     61         tree[now<<1|1].sum=tree[now<<1|1].ls=tree[now<<1|1].rs=tree[now<<1|1].r-tree[now<<1|1].l+1;
     62         tree[now<<1].lazy=tree[now<<1|1].lazy=2;
     63     }
     64     tree[now].lazy=0;
     65 }
     66 void update(int l,int r,int now,int tag)//L R 要修改的区间 tag=1 0->1 tag=2 1->0
     67 {
     68     if(tree[now].l==l&&tree[now].r==r)
     69     {
     70         if(tag==1) tree[now].sum=tree[now].ls=tree[now].rs=0;
     71         else if(tag==2) tree[now].sum=tree[now].ls=tree[now].rs=r-l+1;
     72         tree[now].lazy=tag;
     73         return ;
     74     }
     75     push_down(now);
     76     int mid=(tree[now].l+tree[now].r)>>1;
     77     if(r<=mid) update(l,r,now<<1,tag);
     78     else if(mid<l) update(l,r,now<<1|1,tag);
     79     else 
     80     {
     81         update(l,mid,now<<1,tag);
     82         update(mid+1,r,now<<1|1,tag);
     83     }
     84     push_up(now);
     85 }
     86 int query(int l,int r,int now,int len)
     87 {
     88     if(l==r) return l;
     89     push_down(now);
     90     int mid=(l+r)>>1;
     91     if(tree[now<<1].sum>=len) return query(l,mid,now<<1,len);
     92     else if(tree[now<<1].rs+tree[now<<1|1].ls>=len) return mid-tree[now<<1].rs+1;
     93     else return query(mid+1,r,now<<1|1,len);
     94 }
     95 /////////////////////////////////////////////////////////////////////////////////////////
     96 
     97 int main()
     98 {
     99     // freopen("in.in","r",stdin);
    100     // freopen("out.out","w",stdout);
    101     int n,m;
    102     scanf("%d%d",&n,&m);
    103     build(1,n,1);
    104     for(int i=1;i<=m;i++)
    105     {//tag=1 0->1 tag=2 1->0
    106         int num;
    107         scanf("%d",&num);
    108         if(num==1) 
    109         {
    110             int x;
    111             scanf("%d",&x);
    112             if(tree[1].sum>=x)
    113             {
    114                 int ans=query(1,n,1,x);
    115                 printf("%d
    ",ans);
    116                 update(ans,ans+x-1,1,1);
    117             }
    118             else 
    119             {
    120                 printf("0
    ");
    121             }
    122         }
    123         else if(num==2)
    124         {
    125             int x,y;
    126             scanf("%d%d",&x,&y);
    127             update(x,x+y-1,1,2);
    128         }
    129     }
    130     return 0;
    131 }
  • 相关阅读:
    sql行列互转
    用户角色权限设计思路
    树节点类型数据的Datatable转Json
    [C#]最简单的Base64加密解密
    WEB打印控件Lodop(V6.x)使用说明及样例
    js代码 设为首页 加入收藏
    Json字符转化成对象
    C++函数返回值为const
    7.双指针(two pointer)
    线程同步与锁
  • 原文地址:https://www.cnblogs.com/YangKun-/p/12763386.html
Copyright © 2011-2022 走看看