题解 P3071 【[USACO13JAN]座位Seating】

 

为什么没有题解?似乎讨论版里的也是错的=_= ......

这样的话我就来写一篇吧lalal(`・ω・´)

我有点怀疑标签,毕竟谁能想出这个怎么用(单调)队列写???

懵逼

其实我是用线段树写的。

每个节点(区间)记录三个变量:

sl[i]:从左往右有连续多少个空位

sr[i]:从右往左有连续多少个空位

s[i]:这个区间中最长连续多少个空位

 

 1 //ln指左孩子的区间包含多少座位
 2 //rn指右孩子的区间包含多少座位
 3 //rt指当前节点
 4 
 5 向上更新:
 6 
 7 inline void pu(int rt,int ln,int rn){
 8     s[rt]=max(max(s[ls],s[rs]),sr[ls]+sl[rs]);
 9     sl[rt]=sl[ls]+(sl[ls]==ln)*sl[rs];
10     sr[rt]=sr[rs]+(sr[rs]==rn)*sr[ls];
11 }
12 
13 向下更新:
14 //add指懒惰标记
15 inline void pd(int rt,int ln,int rn){
16     if(!add[rt]||(!ln&&!rn))return;
17     s[ls]=sl[ls]=sr[ls]=(add[rt]>0)*ln;
18     s[rs]=sl[rs]=sr[rs]=(add[rt]>0)*rn;
19     add[ls]=add[rs]=add[rt];add[rt]=0;
20 }

 

相信大家看代码应该是能看得懂的>_<

那么我就来给完整代码了:

 1 #include<bits/stdc++.h>
 2 namespace ZDY{
 3 #define ll long long
 4 #define Fur(i,x,y) for(int i=x;i<=y;i++)
 5 #define in2(x,y) in(x);in(y)
 6 }using namespace ZDY;using namespace std;
 7 #define N 5000011
 8 #define ls rt<<1
 9 #define rs ls|1
10 #define Z int m=(l+r)>>1
11 #define lson l,m,ls
12 #define rson m+1,r,rs
13 ll s[N<<2],sl[N<<2],sr[N<<2];
14 int n,q;
15 short add[N];
16 inline void pu(int rt,int ln,int rn){
17     s[rt]=max(max(s[ls],s[rs]),sr[ls]+sl[rs]);
18     sl[rt]=sl[ls]+(sl[ls]==ln)*sl[rs];
19     sr[rt]=sr[rs]+(sr[rs]==rn)*sr[ls];
20 }
21 inline void pd(int rt,int ln,int rn){
22     if(!add[rt]||(!ln&&!rn))return;
23     s[ls]=sl[ls]=sr[ls]=(add[rt]>0)*ln;
24     s[rs]=sl[rs]=sr[rs]=(add[rt]>0)*rn;
25     add[ls]=add[rs]=add[rt];add[rt]=0;
26 }
27 inline void build(int l,int r,int rt){
28     s[rt]=sl[rt]=sr[rt]=r-l+1;if(l==r)return;
29     Z;build(lson);build(rson);
30 }
31 inline void upd(int L,int R,int l,int r,int rt,int v){
32     if(L<=l&&r<=R){s[rt]=sl[rt]=sr[rt]=(v>0)*(r-l+1),add[rt]=v;return;}
33     Z;pd(rt,m-l+1,r-m);
34     if(L<=m)upd(L,R,lson,v);
35     if(R>m)upd(L,R,rson,v);
36     pu(rt,m-l+1,r-m);
37 }
38 inline int ask(int c,int l,int r,int rt){
39     Z;pd(rt,m-l+1,r-m);
40     if(s[ls]>=c)return ask(c,lson);
41     else if(sr[ls]+sl[rs]>=c)return m-sr[ls]+1;
42     else return ask(c,rson);
43 }
44 int main(){
45      scanf("%d%d",&n,&q);build(1,n,1);
46      int x,y,ans=0,pos;
47      while(q--)
48          if(sc()=='A'){
49              scanf("%d",&x);
50              if(s[1]<x)ans++;
51              else{
52                  pos=ask(x,1,n,1);
53                  upd(pos,pos+x-1,1,n,1,-1);
54              }
55         }
56          else{scanf("%d%d",&x,&y);upd(x,y,1,n,1,1);}
57     cout<<ans<<endl;
58 }
View Code

 好像这题和P2894 [USACO08FEB]酒店Hotel 重复了...

 

转载于:https://www.cnblogs.com/mimiorz/p/9294546.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值