[USACO13JAN] Seating
https://www.luogu.org/problem/show?pid=3071
题目描述
To earn some extra money, the cows have opened a restaurant in their barn specializing in milkshakes. The restaurant has N seats (1 <= N <= 500,000) in a row. Initially, they are all empty.
Throughout the day, there are M different events that happen in sequence at the restaurant (1 <= M <= 300,000). The two types of events that can happen are:
-
A party of size p arrives (1 <= p <= N). Bessie wants to seat the party in a contiguous block of p empty seats. If this is possible, she does so in the lowest position possible in the list of seats. If it is impossible, the party is turned away.
- A range [a,b] is given (1 <= a <= b <= N), and everybody in that range of seats leaves.
Please help Bessie count the total number of parties that are turned away over the course of the day.
有一排n个座位,m次操作。A操作:将a名客人安置到最左的连续a个空位中,没有则不操作。L操作:[a,b]的客人离开。
求A操作的失败次数。
输入输出格式
输入格式:
-
Line 1: Two space-separated integers, N and M.
- Lines 2..M+1: Each line describes a single event. It is either a line of the form "A p" (meaning a party of size p arrives) or "L a b" (meaning that all cows in the range [a, b] leave).
输出格式:
- Line 1: The number of parties that are turned away.
输入输出样例
10 4 A 6 L 2 4 A 5 A 2
1
线段树
实践再次证明:数组比结构体要快
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; int n,m,x,y,opl,opr; #define N 500001*4 int maxx[N],max_l[N],max_r[N],sum[N],flag[N]; void build(int k,int l,int r) { sum[k]=maxx[k]=max_l[k]=max_r[k]=r-l+1; if(l==r) return; int mid=l+r>>1; build(k<<1,l,mid);build((k<<1)+1,mid+1,r); } void down(int k) { flag[k<<1]=flag[(k<<1)+1]=flag[k]; if(flag[k]==1) maxx[k<<1]=max_l[k<<1]=max_r[k<<1]=maxx[(k<<1)+1]=max_l[(k<<1)+1]=max_r[(k<<1)+1]=0; else { maxx[k<<1]=max_l[k<<1]=max_r[k<<1]=sum[k<<1]; maxx[(k<<1)+1]=max_l[(k<<1)+1]=max_r[(k<<1)+1]=sum[(k<<1)+1]; } flag[k]=0; } int ask(int k,int l,int r) { if(l==r) return l; if(flag[k]) down(k); int mid=l+r>>1; if(maxx[k<<1]>=x) return ask(k<<1,l,mid); if(max_l[(k<<1)+1]+max_r[k<<1]>=x) return mid-max_r[k<<1]+1; return ask((k<<1)+1,mid+1,r); } void up(int k) { maxx[k]=max(max(maxx[k<<1],maxx[(k<<1)+1]),max_r[k<<1]+max_l[(k<<1)+1]); if(sum[k<<1]==maxx[k<<1]) max_l[k]=sum[k<<1]+max_l[(k<<1)+1]; else max_l[k]=max_l[k<<1]; if(sum[(k<<1)+1]==maxx[(k<<1)+1]) max_r[k]=sum[(k<<1)+1]+max_r[k<<1]; else max_r[k]=max_r[(k<<1)+1]; } void change(int k,int f,int l,int r) { if(l>=opl&&r<=opr) { if(f==1) { maxx[k]=max_l[k]=max_r[k]=0; flag[k]=1; return; } else { maxx[k]=max_l[k]=max_r[k]=sum[k]; flag[k]=2; return; } } if(flag[k]) down(k); int mid=l+r>>1; if(opr<=mid) change(k<<1,f,l,mid); else if(opl>mid) change((k<<1)+1,f,mid+1,r); else { change(k<<1,f,l,mid); change((k<<1)+1,f,mid+1,r); } up(k); } void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } int main() { int cnt=0; char p[2]; read(n); read(m); build(1,1,n); for(int i=1;i<=m;i++) { scanf("%s",p); if(p[0]=='A') { read(x); if(maxx[1]<x) cnt++; else { opl=ask(1,1,n); opr=opl+x-1; change(1,1,1,n); } } else { read(opl); read(opr); change(1,2,1,n); } } printf("%d",cnt); }