zoukankan      html  css  js  c++  java
  • POJ 3667 线段树的区间合并简单问题

    题目大意:
    有一排标号1-N的房间。
    操作一:询问是不是有连续长度为a的空房间,有的话住进最左边(占用a个房间)
    操作二:将[a,a+b-1]的房间清空(腾出b个房间)
    思路:记录每个区间中“靠左”“靠右”“中间”的空房间
    线段树操作:update:区间替换
    query:询问满足条件的最左端点

    题目链接:

    http://vjudge.net/problem/viewProblem.action?id=10354

    题目操作:

    因为这里找从最左边住起的房间,所以这里不能像常规地写query函数那样写了,终于发现自己只会套模板的下场的悲哀了,智商拙计啊T T

    而且你在query函数,因为要尽可能找左边的房间,所以要从左边先递归

    1.

    int query(int cur,int x,int y,int w)
    {
        int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1;
        if(x==y) return x //这里是表示找到树的底层无叶节点了就结束函数,同时也防止找不到点,其实这里如果找不到所求点的话,会不断进入右子树最后抵达最大的子节点返回
        pushdown(cur,x,y);
        if(mc[cur<<1]>=w) return query(ls,x,mid,w);  //如果左侧能找到满足的点,我们不断朝左侧进行递归
        else if(rc[cur<<1]+lc[cur<<1|1]>=w) return mid-rc[cur<<1]+1;//左侧不成立我们在开始找中间并在一起形成的房间的最左侧点
        return query(rs,mid+1,y,w);  //左侧中间都不成立,那么只能进入右子树进行找点
    }
    因为这个query函数必然有返回值,所以,我们在主函数中必须先进行判断能否找到适合的一连串的房间,然后再进行ans=query(1,1,n,w)操作以及后面的房间入住的覆盖操作。

    这个判断很简单 1为线段树根节点,所以mc[1]其实是最大的连续最长房间,if(mc[1]>=w)这个判断执行就可以了

    这里介绍一下puts("0"):
    puts()函数用来向标准输出设备(屏幕)写字符串并换行,其调用方式为,puts(s);其中s为字符串字符(字符串数组名或字符串指针)。

    所以这道题puts("0");就输出了不存在的情况

    2.

    当然我也可以换种方式在query的函数里面进行一下小小的修改,使得它在不能找到房间的时候输出-1;

    int query(int cur,int x,int y,int w)
    {
        int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1;
        if(x==y) return mc[cur]<w?-1:x; //在这修改一下,然后直接在main函数中判断为-1,那么输出0即可
        pushdown(cur,x,y);
        if(mc[cur<<1]>=w) return query(ls,x,mid,w);
        else if(rc[cur<<1]+lc[cur<<1|1]>=w) return mid-rc[cur<<1]+1;
        return query(rs,mid+1,y,w);
    }

    总代码如下:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 #define N 50010
     6 #define L ls,x,mid
     7 #define R rs,mid+1,y
     8 int rev[N<<2],lc[N<<2],rc[N<<2],mc[N<<2];
     9 void update(int cur,int x,int y)
    10 {
    11     int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
    12     lc[cur]=lc[ls],rc[cur]=rc[rs];
    13     mc[cur]=max(mc[ls],mc[rs]);
    14     mc[cur]=max(mc[cur],rc[ls]+lc[rs]);
    15     if(lc[ls]==mid-x+1) lc[cur]=lc[ls]+lc[rs];
    16     if(rc[rs]==y-mid) rc[cur]=rc[rs]+rc[ls];
    17 }
    18 void build(int cur,int x,int y)
    19 {
    20     int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
    21     rev[cur]=-1;
    22     if(x==y){
    23         lc[cur]=rc[cur]=mc[cur]=1;
    24         return;
    25     }
    26     build(ls,x,mid);
    27     build(rs,mid+1,y);
    28     update(cur,x,y);
    29 }
    30 void pushdown(int cur,int x,int y)
    31 {
    32     int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
    33     if(rev[cur]!=-1){
    34         if(rev[cur]==1){
    35             rev[ls]=rev[rs]=1;
    36             lc[ls]=rc[ls]=mc[ls]=lc[rs]=rc[rs]=mc[rs]=0;
    37             rev[cur]=-1;
    38         }
    39         else if(rev[cur]==0){
    40             rev[ls]=rev[rs]=0;
    41             lc[ls]=rc[ls]=mc[ls]=mid-x+1;
    42             lc[rs]=rc[rs]=mc[rs]=y-mid;
    43             rev[cur]=-1;
    44         }
    45     }
    46 }
    47 void change(int cur,int x,int y,int s,int t,int v)
    48 {
    49     int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1;
    50     if(x>=s&&y<=t){
    51         rev[cur]=v;
    52         lc[cur]=rc[cur]=mc[cur]=v?0:y-x+1;
    53         return;
    54     }
    55     pushdown(cur,x,y);
    56     if(mid>=s) change(ls,x,mid,s,t,v);
    57     if(mid+1<=t) change(rs,mid+1,y,s,t,v);
    58     update(cur,x,y);
    59 }
    60 int query(int cur,int x,int y,int w)
    61 {
    62     int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1;
    63     if(x==y) return x;
    64     pushdown(cur,x,y);
    65     if(mc[cur<<1]>=w) return query(ls,x,mid,w);
    66     else if(rc[cur<<1]+lc[cur<<1|1]>=w) return mid-rc[cur<<1]+1;
    67     return query(rs,mid+1,y,w);
    68 }
    69 int main()
    70 {
    71     int n,m,op,a,b;
    72     while(scanf("%d%d",&n,&m)!=EOF){
    73         build(1,1,n);
    74         for(int i=0;i<m;i++){
    75             scanf("%d",&op);
    76             if(op==1){
    77                 scanf("%d",&a);
    78                 if(mc[1]<a) puts("0");
    79                 else{
    80                     int ans=query(1,1,n,a);
    81                     printf("%d
    ",ans);
    82                     change(1,1,n,ans,ans+a-1,1);
    83                 }
    84             }
    85             else{
    86                 scanf("%d%d",&a,&b);
    87                 change(1,1,n,a,a+b-1,0);
    88             }
    89         }
    90     }
    91     return 0;
    92 }
  • 相关阅读:
    英文综述如何写6
    英文综述如何写5
    英文综述如何写4
    英文综述如何写3
    英文综述如何写2
    英文综述如何写
    Python开发【第三篇】:Python基本数据类型
    Python开发【第二篇】:初识Python
    Python开发【第一篇】:目录
    第二十单元 计划任务crond服务
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/3897393.html
Copyright © 2011-2022 走看看