POJ - 3667 Hotel(线段树区间合并)
Posted windystreet
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ - 3667 Hotel(线段树区间合并)相关的知识,希望对你有一定的参考价值。
题意:
给定一个有$N$个车位的停车场(都在一条直线上),现在有有两种操作
$1.x $ 要停连续的停$x$辆车,输出第一辆车停的位置(尽量靠前),不能就输出$0$;
$2.x,d$ 从x位置开始开走连续的$d$辆车。
思路:
一个线段树区间和问题,而且满足区间可加性,就要用到区间合并。
1 /* 2 * Author: windystreet 3 * Date : 2018-08-15 10:29:55 4 * Motto : Think twice, code once. 5 */ 6 #include <stdio.h> 7 #include <string.h> 8 #include <algorithm> 9 10 using namespace std; 11 12 #define X first 13 #define Y second 14 #define eps 1e-5 15 #define gcd __gcd 16 #define pb push_back 17 #define PI acos(-1.0) 18 #define lowbit(x) (x)&(-x) 19 #define bug printf("!!!!! "); 20 #define mem(x,y) memset(x,y,sizeof(x)) 21 22 typedef long long LL; 23 typedef long double LD; 24 typedef pair<int,int> pii; 25 typedef unsigned long long uLL; 26 27 const int maxn = 5e4+7; 28 const int INF = 1<<30; 29 const int mod = 1e9+7; 30 31 struct Tree 32 { 33 int l,r,lazy; 34 int ls,rs,ms; // 区间前缀,后缀,最大值 35 }tree[maxn<<2]; 36 void build(int rt,int l,int r){ 37 tree[rt].r = r;tree[rt].l = l;tree[rt].lazy = -1; 38 if(l == r){ 39 tree[rt].ms = tree[rt].ls = tree[rt].rs = 1;return; 40 } 41 int mid = ( l + r ) >> 1; 42 build(rt<<1,l,mid); 43 build(rt<<1|1,mid+1,r); 44 tree[rt].ms = tree[rt].ls = tree[rt].rs = tree[rt<<1].ms + tree[rt<<1|1].ms; 45 } 46 void pushdown(int rt){ 47 if(tree[rt].lazy!=-1){ // 下推标记 48 int mid = (tree[rt].r + tree[rt].l )>>1; 49 tree[rt<<1|1].lazy = tree[rt<<1].lazy = tree[rt].lazy; 50 tree[rt<<1].ls = tree[rt<<1].rs = tree[rt<<1].ms = (mid - tree[rt].l+1)*tree[rt].lazy; 51 tree[rt<<1|1].ls = tree[rt<<1|1].rs = tree[rt<<1|1].ms = (tree[rt].r -mid)*tree[rt].lazy; 52 tree[rt].lazy = -1; 53 } 54 } 55 void pushup(int rt){ // 向上更新 56 tree[rt].ls = tree[rt<<1].ls; 57 tree[rt].rs = tree[rt<<1|1].rs; 58 if(tree[rt<<1].ls == (tree[rt<<1].r - tree[rt<<1].l + 1)){ // 区间合并 59 tree[rt].ls += tree[rt<<1|1].ls; 60 } 61 if(tree[rt<<1|1].rs == (tree[rt<<1|1].r - tree[rt<<1|1].l + 1)){ 62 tree[rt].rs += tree[rt<<1].rs; 63 } 64 tree[rt].ms = max(max(tree[rt<<1|1].ms,tree[rt<<1].ms),tree[rt<<1].rs+tree[rt<<1|1].ls); 65 } 66 void update(int rt,int L,int R,int l,int r,int v){ 67 if(l<=L&&R<=r){ 68 tree[rt].ls = tree[rt].rs = tree[rt].ms = v*(R - L + 1); 69 tree[rt].lazy = v;return; 70 } 71 pushdown(rt); 72 int mid = ( L + R) >>1; 73 if(l<=mid) update(rt<<1,L,mid,l,r,v); 74 if(r>mid) update(rt<<1|1,mid+1,R,l,r,v); 75 pushup(rt); 76 } 77 int query(int rt,int L,int R,int v){ 78 pushdown(rt); 79 int mid = (L + R) >>1; 80 if(tree[rt<<1].ms>=v){ // 尽量靠前 81 return query(rt<<1,L,mid,v); 82 }else if(tree[rt<<1].rs + tree[rt<<1|1].ls>=v){ 83 return mid - tree[rt<<1].rs + 1; 84 }else{ 85 return query(rt<<1|1,mid+1,R,v); 86 } 87 } 88 89 void solve(){ 90 int n,m,op,x,y; 91 while(scanf("%d%d",&n,&m)!=EOF){ 92 build(1,1,n); 93 while(m--){ 94 scanf("%d",&op); 95 if(op==1){ 96 scanf("%d",&x); 97 if(tree[1].ms<x){ 98 puts("0"); 99 }else{ 100 int pos = query(1,1,n,x); 101 printf("%d ",pos); 102 update(1,1,n,pos,pos+x-1,0); 103 } 104 105 }else{ 106 scanf("%d%d",&x,&y); 107 update(1,1,n,x,x+y-1,1); 108 } 109 } 110 } 111 112 return; 113 } 114 115 int main() 116 { 117 // freopen("F:\in.txt","r",stdin); 118 // freopen("out.txt","w",stdout); 119 // ios::sync_with_stdio(false); 120 int t = 1; 121 //scanf("%d",&t); 122 while(t--){ 123 // printf("Case %d: ",cas++); 124 solve(); 125 } 126 return 0; 127 }
以上是关于POJ - 3667 Hotel(线段树区间合并)的主要内容,如果未能解决你的问题,请参考以下文章