[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:

  1. 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.

  2. 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.

 

输入输出样例

输入样例#1:
10 4 
A 6 
L 2 4 
A 5 
A 2 
输出样例#1:
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);
}

 

posted @ 2017-08-18 15:32  TRTTG  阅读(424)  评论(0编辑  收藏  举报