线段树||BZOJ1593: [Usaco2008 Feb]Hotel 旅馆||Luogu P2894 [USACO08FEB]酒店Hotel

题面:P2894 [USACO08FEB]酒店Hotel 

题解:和基础的线段树操作差别不是很大,就是在传统的线段树基础上多维护一段区间最长的合法前驱(h_),最长合法后驱(t_),一段中最长的合法区间(mx)。询问时由于查询的是最左边的合法端点,所以要从左到中间到右边依次考虑情况。

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #define max(a,b) ((a)>(b)?(a):(b))
 5 using namespace std;
 6 const int maxn=50000+5,maxm=50000+5;
 7 int N,M,o,D,X,ans;
 8 inline int rd(){
 9     int x=0;char c=getchar();
10     while(c<'0'||c>'9')c=getchar();
11     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
12     return x;
13 }
14 struct Tree{
15     int l,r,lazy,h_,t_,mx;
16 }t[maxn<<2];
17 inline void Pushup(int x){
18     int ls=x<<1,rs=x<<1|1;
19     if(t[ls].r-t[ls].l+1==t[ls].mx)t[x].h_=t[ls].mx+t[rs].h_;else t[x].h_=t[ls].h_;
20     if(t[rs].r-t[rs].l+1==t[rs].mx)t[x].t_=t[rs].mx+t[ls].t_;else t[x].t_=t[rs].t_;
21     t[x].mx=max(t[ls].mx,t[rs].mx);
22     t[x].mx=max(t[x].mx,t[ls].t_+t[rs].h_);
23     return;
24 }
25 inline void Build(int x,int l,int r){
26     t[x].l=l;t[x].r=r;t[x].lazy=-1;
27     if(l==r){
28         t[x].h_=t[x].t_=t[x].mx=1;
29         return;
30     }
31     int mid=(l+r)>>1;
32     Build(x<<1,l,mid);Build(x<<1|1,mid+1,r);
33     Pushup(x);
34     return;
35 }
36 inline void Pushdown(int x){
37     if(t[x].lazy>=0){
38         int k=t[x].lazy,ls=x<<1,rs=x<<1|1;t[x].lazy=-1;
39         if(k==1){
40             t[ls].h_=t[ls].t_=t[ls].mx=0;
41             t[rs].h_=t[rs].t_=t[rs].mx=0;
42         }
43         else{
44             t[ls].h_=t[ls].t_=t[ls].mx=t[ls].r-t[ls].l+1;
45             t[rs].h_=t[rs].t_=t[rs].mx=t[rs].r-t[rs].l+1;
46         }
47         t[ls].lazy=t[rs].lazy=k;
48     }
49     return;
50 }
51 inline int Solve(int x,int d){
52     int ls=x<<1,rs=x<<1|1,l=t[x].l,r=t[x].r;
53     if(r-l+1==t[x].mx&&t[x].mx==d)return l;
54     Pushdown(x);
55     if(t[ls].mx>=d)return Solve(ls,d);
56     if(t[ls].t_+t[rs].h_>=d)return (t[ls].r-t[ls].t_+1);
57     if(t[rs].mx>=d)return Solve(rs,d);
58     return 0;
59 }
60 inline void Update(int x,int ql,int qr,int o){
61     int l=t[x].l,r=t[x].r;
62     if(ql<=l&&r<=qr){
63         if(o==1)t[x].h_=t[x].t_=t[x].mx=0;
64         else t[x].h_=t[x].t_=t[x].mx=r-l+1;
65         t[x].lazy=o;
66         return;
67     }
68     int mid=(l+r)>>1,ls=x<<1,rs=x<<1|1;
69     Pushdown(x);
70     if(ql<=mid)Update(ls,ql,qr,o);
71     if(qr>mid)Update(rs,ql,qr,o);
72     Pushup(x);
73     return;
74 }
75 inline void write(int x){
76     char a[12];int len=0;
77     for(;x;x/=10)a[len++]=x%10;
78     if(!len)putchar('0');
79     else while(len)putchar(a[--len]+'0');
80     putchar('\n');
81 }
82 int main(){
83     N=rd();M=rd();
84     Build(1,1,N);
85     while(M--){
86         o=rd();
87         if(o==1){
88             D=rd();
89             ans=Solve(1,D);
90             write(ans);
91             if(ans)Update(1,ans,ans+D-1,1);//1表示有住人 
92         }
93         else{
94             X=rd();D=rd();
95             Update(1,X,X+D-1,0);
96         }
97     }
98     return 0;
99 }

//我为了卡常加入了快速读入和快速输出,实际食用代码时完全可以无视。


By:AlenaNuna

猜你喜欢

转载自www.cnblogs.com/AlenaNuna/p/10357986.html