【BZOJ3050】【USACO 2013 Jan Gold金组】坐座位 Seating

原创 2016年08月28日 21:44:17

【USACO 2013 1月金组】seating

时间限制: 1 Sec 内存限制: 128 MB

题目描述

为了赚更多的钱,奶牛场开了一间专门做奶昔的餐馆。这个餐馆有N个位子(1<=N<=500000)排成一行,开始时,位子都是空的。
每天,有M个不同的事件按次序发生(1<=M<=300000).事件分为两类:
1.举办一个party,这个party有p头奶牛(1<=p<=N),这p头奶牛只会坐在相邻的位子。如果没有p个连续的空位,则奶牛们会离开。如果有多个,奶牛们会选择起点编号最小的一段空位。
2.区间[a,b]的奶牛们离开座位。(1<=a

输入

第一行:两个整数N,M。
第二行到第M+1行:每一行表示一个事件,它要么是形如“A p”,表示有一个party,这个party有p头奶牛;要么是形如L a b 的一行,表示区间[a,b]的所有奶牛全部离开。

输出

一行,表示不满足要求的聚会个数。

样例输入

10 4
A 6
L 2 4
A 5
A 2

样例输出

1

解题报告:

某天考试题。。。
比较裸的线段树题目,关键在于代码实现有点难(考试时没调出来)
用线段树控制区间的删除与增加,
每个线段树上节点,维护3个变量le,max,re。

struct Node{
    int l,r;
    int le,re,max;
    int lz;
}nodes[MAXN*5];

他们分别表示该区间内部靠左的空间大小,区间中不与左右空区间接触的最大空区间大小,该区间内部靠右的空区间大小。
每次updata操作这样写:

inline void updata(int u){
    nodes[u].max=maxf(nodes[u<<1].max,nodes[(u<<1)+1].max);
    nodes[u].max=maxf(nodes[u].max,nodes[u<<1].re+nodes[(u<<1)+1].le);
    le[u]=nodes[u<<1].le;
    re[u]=nodes[(u<<1)+1].re;
    if(nodes[u<<1].le==nodes[u<<1].r-nodes[u<<1].l+1)
        le[u]+=nodes[(u<<1)+1].le;
    if(nodes[(u<<1)+1].re==nodes[(u<<1)+1].r-nodes[(u<<1)+1].l+1)
        re[u]+=nodes[u<<1].re;
}

lazy标记保存三个值,非别是0,1,2
代表无操作,填满和清空

const int REMOVE=2;
const int FILL=1;

下传lazy时这么写:

inline void pushdown(int index){
    nodes[index<<1].lz=nodes[(index<<1)+1].lz=nodes[index].lz;
    if(nodes[index].lz==FILL){
        nodes[index<<1].le=nodes[index<<1].re=nodes[index<<1].max=0;
        nodes[(index<<1)+1].le=nodes[(index<<1)+1].re=nodes[(index<<1)+1].max=0;
    }
    else if(nodes[index].lz==REMOVE){
        nodes[index<<1].max=nodes[index<<1].re=nodes[index<<1].le
        =nodes[index<<1].r-nodes[index<<1].l+1;
        nodes[(index<<1)+1].max=nodes[(index<<1)+1].re=nodes[(index<<1)+1].le
        =nodes[(index<<1)+1].r-nodes[(index<<1)+1].l+1;
    }
    nodes[index].lz=0;
}

由于每次A操作要寻找一段最靠左长度为len的空区间
因此多添加一个函数:

int len;
int query(int u){
    if(nodes[u].l==nodes[u].r)return nodes[u].l;
    if(nodes[u].lz)
        pushdown(u);
    if(nodes[u<<1].max>=len)return query(u<<1);
    else if(nodes[u<<1].re+nodes[(u<<1)+1].le>=len)
        return nodes[u<<1].r-nodes[u<<1].re+1;
    else return query((u<<1)+1);
}

此函数用于寻找长度为len的空区间左端点位置
原理:在保持当前区间中最大空区间长度大于len时尽量向左儿子前进,最后找到的一定是最靠左的区间。

下面发AC代码:

#include<cstdio>
const int MAXN=510000;
const int MAXM=310000;
const int REMOVE=2;
const int FILL=1;
inline int max(const int &a,const int &b)
{return a<b?b:a;}
inline int min(const int &a,const int &b)
{return a<b?a:b;}
inline void getint(int &t){
    register char c;t=0;
    do{c=getchar();}while(c<'0'||c>'9');
    while(c<='9'&&c>='0'){t=t*10+c-'0';c=getchar();}
}
struct Node{
    int l,r;
    int le,re,max;
    int lz;
}nodes[MAXN*5];
inline void pushdown(int index){
    nodes[index<<1].lz=nodes[(index<<1)+1].lz=nodes[index].lz;
    if(nodes[index].lz==FILL){
        nodes[index<<1].le=nodes[index<<1].re=nodes[index<<1].max=0;
        nodes[(index<<1)+1].le=nodes[(index<<1)+1].re=nodes[(index<<1)+1].max=0;
    }
    else if(nodes[index].lz==REMOVE){
        nodes[index<<1].max=nodes[index<<1].re=nodes[index<<1].le
        =nodes[index<<1].r-nodes[index<<1].l+1;
        nodes[(index<<1)+1].max=nodes[(index<<1)+1].re=nodes[(index<<1)+1].le
        =nodes[(index<<1)+1].r-nodes[(index<<1)+1].l+1;
    }
    nodes[index].lz=0;
}
inline void updata(int u){
    nodes[u].max=max(nodes[u<<1].max,nodes[(u<<1)+1].max);
           nodes[u].max=max(nodes[u].max,nodes[u<<1].re+nodes[(u<<1)+1].le);
    nodes[u].le=nodes[u<<1].le;
    nodes[u].re=nodes[(u<<1)+1].re;
    if(nodes[u<<1].le==nodes[u<<1].r-nodes[u<<1].l+1)
        nodes[u].le+=nodes[(u<<1)+1].le;
    if(nodes[(u<<1)+1].re==nodes[(u<<1)+1].r-nodes[(u<<1)+1].l+1)
        nodes[u].re+=nodes[u<<1].re;
}
void build(int u,int l,int r){
    nodes[u].l=l;
    nodes[u].r=r;
    nodes[u].le=nodes[u].re=nodes[u].max=r-l+1;
    if(l==r)return ;
    int mid=(l+r)>>1;
    build(u<<1,l,mid);
    build((u<<1)+1,mid+1,r);
}
int l,r,k;
void fill(int u){
    if(nodes[u].r<l||nodes[u].l>r)return ;
    if(nodes[u].lz)
        pushdown(u);
    if(nodes[u].l>=l&&nodes[u].r<=r){
        nodes[u].lz=k;
        if(k==REMOVE)nodes[u].le=nodes[u].re=nodes[u].max=nodes[u].r-nodes[u].l+1;
        else nodes[u].le=nodes[u].re=nodes[u].max=0;
        return ;
    }
    fill(u<<1);
    fill((u<<1)+1);
    updata(u);
}
int len;
int query(int u){
    if(nodes[u].l==nodes[u].r)return nodes[u].l;
    if(nodes[u].lz)
        pushdown(u);
    if(nodes[u<<1].max>=len)return query(u<<1);
    else if(nodes[u<<1].re+nodes[(u<<1)+1].le>=len)
        return nodes[u<<1].r-nodes[u<<1].re+1;
    else return query((u<<1)+1);
}
int main(){
    int n,m;
    getint(n),getint(m);
    build(1,1,n);
    int ans=0;
    register char o;
    register int a,b,c;
    for(int i=1;i<=m;i++){
        while((o=getchar())!='L'&&o!='A');
        if(o=='L'){
            getint(a);
            getint(b);
            l=a;
            r=b;
            k=REMOVE;
            fill(1);
        }else {
            getint(c);
            if(c>nodes[1].max){ans++;continue;}
            len=c;
            int pos=query(1);
            l=pos;
            r=pos+c-1;
            k=FILL;
            fill(1);
        }
    }
    printf("%d\n",ans);
}
//ORZ GJY LJH  TSY SYK YLY GMR YMX

此题在bzoj上每个点给了10秒的时限,但是在学校oj上只给一秒。。。
于是就成了卡常神题 = =

我从两天前开始就是一阵狂T,把能想到的inline,读入优化,等等全部写上,再把函数参数全改成全局变量,
结果是这样的:
哎
= =
心酸呐= =
然后只好在群里求助大神,大神说加个注释就能保证卡过!
于是加上:

//ORZ GJY LJH  TSY SYK YLY GMR YMX

然后果然交了两发就过了啊哈哈哈

===============================分割线===============================
PS
据说这道题有华丽丽的常数超小不会被卡的差分做法

版权声明:本文为博主原创文章,未经博主允许可以随便转载[滑稽],但请注明出处。

相关文章推荐

bzoj 3050: [Usaco2013 Jan] Seating

Description To earn some extra money, the cows have opened a restaurant in their barn specializing ...

[BZOJ3050][Usaco2013 Jan]Seating(线段树)

最可耻的诬陷,总是彬彬有礼。

BZOJ 3050: [Usaco2013 Jan] Seating

DescriptionTo earn some extra money, the cows have opened a restaurant in their barn specializing in...

BZOJ 4510|USACO 2016 Jan Gold|Ratio Contact|动态规划

John和Bessie分别从(fx,fy)和(bx,by)出发,他们通过无线电通讯,单位时间消耗能量大小等于两人距离的平方(但他们同时在出发点的开始时刻的能量不算),为了节约能量,他们尽量靠在一起。单...

BZOJ1574 USACO 2009 Jan Gold 1.Earthquake Damage Solution

要想被截掉的点越少,最优方案就是不可行点周围的点都损坏。然后bfs一下求出从1能到达的点,剩下的就是不能的了。 一定要注意:这是图,不是树!有可能有自环,有重边。 #include #includ...

[BZOJ3049][Usaco2013 Jan]Island Travels(dfs+spfa+状压dp)

最不洁的目光,总在监察道德。

【bzoj 3049】[Usaco2013 Jan]Island Travels(状压dp)

又是一年枯黄,枫叶红了满面秋霜

BZOJ 3049: [Usaco2013 Jan]Island Travels

DescriptionFarmer John has taken the cows to a vacation out on the ocean! The cows are living on N (...

BZOJ 3049: [Usaco2013 Jan]Island Travels

DescriptionFarmer John has taken the cows to a vacation out on the ocean! The cows are living on N (...

[USACO 2011Jan Gold]道路与航线

Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查。他想把牛奶送到T个城镇 (1 了一些政策保证:如果有一条航线可以从A_i到B_i,那么保证不可能通过一些道路和航线从B_i回到A_...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)