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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM