zoukankan      html  css  js  c++  java
  • Poj 3667 Hotel 线段树区间合并

    最近一直在看胡浩的【完全版】线段树,这个题目是在他的blog介绍的

    文字没有参考别人的成分

    题目大意:Hotel有N(1 ≤ N ≤ 50,000)间rooms,并且所有的rooms都是连续排列在同一边,groups需要check in 房间,要求房间的编号为连续的r..r+Di-1并且r是最小的;visitors同样可能check out,并且他们每次check out都是编号为Xi ..Xi +Di-1 (1 ≤ XiN-Di+1)的房间,题目的输入有两种样式:

    1. 1  a     :  groups需要check in  a间编号连续的房间
    2. 2  a   b : visitors  check out 房间,其中房间编号是 a…a+b-1

    要求对于每次request,输出为groups分配数目为a的房间中编号最小的房间编号

    思路:利用线段树建立模型,维护最大连续区间长度,其中区间长度就是对应的房间数目,并且对应区间中最左边的断点就是answer,同时因为需要求出连续区间的最大长度,因此每次PushUp时都将左右区间合并,lsum维护左区间的最大长度,rsum维护右区间的最大长度,sum维护区间1…N中的最大连续区间长度,cover标志对应区间是否为空(没有住客)

    具体实现过程:

    BuildTree:建立一颗线段树,其中lsum,rsum,sum初始化为对应区间的长度

    Query   :询问是否有长度为a的连续区间,如果有,返回对应区间的最左边的断点

    UpData  :更新线段树的信息

    PushUp  :将左右子区间合并

    PushDown :标志向下传,延迟标志,简单来说就是先标志,然后等到下次询问或者更新时再去更新线段树

    代码:

      1 #include <stdio.h>
      2 
      3 #define lson l, m, rt<<1
      4 #define rson m+1, r, rt<<1|1
      5 
      6 const int maxn = 50000;
      7 
      8 int n, mNum, op, a, b;
      9 int sum[maxn*3], lsum[maxn*3], rsum[maxn*3], cover[maxn*3];
     10 
     11 void BuildTree(int l, int r, int rt)
     12 {
     13     cover[rt] = -1;
     14     lsum[rt] = rsum[rt] = sum[rt] = r-l+1;
     15     if (l == r)
     16         return ;
     17     
     18     int m = (l+r)>>1;
     19     BuildTree(lson);
     20     BuildTree(rson);
     21 }/* BuildTree */
     22 
     23 void PushDown(int rt, int k)
     24 {
     25     if (cover[rt] != -1)
     26     {   /* Lazy Tag */
     27         cover[rt<<1] = cover[rt<<1|1] = cover[rt];
     28         lsum[rt<<1] = rsum[rt<<1] = sum[rt<<1] = cover[rt] ? 0:(k-(k>>1)); 
     29         lsum[rt<<1|1] = rsum[rt<<1|1] = sum[rt<<1|1] = cover[rt] ? 0:(k>>1);
     30         cover[rt] = -1;
     31     }
     32 }/* PushDown */
     33 
     34 int query(int w, int l, int r, int rt)
     35 {
     36     if (l == r)
     37         return 1;
     38     
     39     PushDown(rt, r-l+1);    /* Push Down */
     40     
     41     int m = (l+r)>>1;
     42     if (sum[rt<<1] >= w)    /* 左连续区间长度 */ 
     43         return query(w, lson);
     44     else if (rsum[rt<<1]+lsum[rt<<1|1] >= w) /* 左区间后半部分与右区间左半部分长度 */ 
     45         return m-rsum[rt<<1]+1;
     46     else                    /* 右连续区间长度 */ 
     47         return query(w, rson);
     48 }/* query */
     49 
     50 int Max(int x, int y)
     51 {
     52     return (x>y ? x:y);
     53 }/* Max */
     54 
     55 void PushUp(int rt, int k)
     56 {
     57     lsum[rt] = lsum[rt<<1];   /* 左区间的左半部分 */ 
     58     rsum[rt] = rsum[rt<<1|1]; /* 右区间的右半部分 */ 
     59     
     60     if (lsum[rt] == k-(k>>1))
     61         lsum[rt] += lsum[rt<<1|1];
     62     if (rsum[rt] == k>>1)
     63         rsum[rt] += rsum[rt<<1];
     64     
     65     sum[rt] = Max(rsum[rt<<1]+lsum[rt<<1|1], Max(sum[rt<<1], sum[rt<<1|1]));
     66 }/* PushUp */
     67 
     68 void UpData(int L, int R, int c, int l, int r, int rt)
     69 {
     70     if (L<=l && r<=R)
     71     {
     72         lsum[rt] = rsum[rt] = sum[rt] = c ? 0 : r-l+1;
     73         cover[rt] = c;
     74         
     75         return ;
     76     }/* End of If */
     77     
     78     PushDown(rt, r-l+1);    /* Push Down */
     79     
     80     int m = (l+r)>>1;
     81     if (L <= m)
     82         UpData(L, R, c, lson);
     83     if (R > m)
     84         UpData(L, R, c, rson);
     85     
     86     PushUp(rt, r-l+1);      /* Push Up */
     87 }/* Updata */
     88 
     89 int main()
     90 {
     91     scanf("%d %d", &n, &mNum);
     92     
     93     BuildTree(1, n, 1); /* BuildTree */ 
     94     for (int i=1; i<=mNum; ++i)
     95     {
     96         scanf("%d", &op);
     97         if (op == 1)
     98         {   // Request
     99             scanf("%d", &a);
    100             if (sum[1] < a)
    101                 printf("0\n");  /* No result */
    102             else
    103             {
    104                 int pos = query(a, 1, n, 1);
    105                 printf("%d\n", pos);
    106                 UpData(pos, pos+a-1, 1, 1, n, 1);   /* UpData the interval */
    107             }
    108         }/* End of If */
    109         else
    110         {
    111             scanf("%d %d", &a, &b);
    112             UpData(a, a+b-1, 0, 1, n, 1);   /* UpData the interval */
    113         }
    114     }/* End of For */
    115     
    116     return 0;
    117 }
  • 相关阅读:
    MySQL基础知识总结
    PHP常见算法
    PHP程序功能设计
    SVN配置使用及移植
    推荐一个SpringBoot + Vue + MyBatis 音乐网站项目
    累积sql常用查询语句「Oracle」
    Nginx服务器设置http/https正向代理,使用ngx_http_proxy_connect_module模块
    squid配置文件
    nginx命令
    k8s与Docker有啥关系
  • 原文地址:https://www.cnblogs.com/yewei/p/2484471.html
Copyright © 2011-2022 走看看