码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj-1135 Lyz

时间:2015-09-17 08:51:02      阅读:157      评论:0      收藏:0      [点我收藏+]

标签:bzoj   poi   线段树   二分图   

题意:

初始时滑冰俱乐部有1到n号的溜冰鞋各k双,x号脚的人可以穿x到x+d的溜冰鞋,;

有m次操作,每次包含两个数ri,xi,代表来了xi个ri号脚的人(xi可能为负);

对于每次操作,输出溜冰鞋是否足够;

n<=200000,m<=500000,k<=10^9;


题解:

首先这是一个二分图匹配问题,显然鞋和人是没有交集的;

然后就有一个Hall定理:

二部图G中的两部分顶点组成的集合分别为X, Y;

边集中有一组无公共点的边,一端恰好为组成X的所有点的充分必要条件是:
X中的任意k个点至少与Y中的k个点相邻;(1≤k≤m)

相邻指有边相连,在x中任选k个我们用任选一段区间代替;

所以在一段区间[l,r]中,令x号脚的人数为F(x);

有∑F(i)<=(r-l+d+1)*k  (l<=i<=r)成立;

将每个F(i)都减一个k,不等式可化为;

∑(F(i)-k)<=d*k  (l<=i<=r);

这个式子任选一段区间都成立;

那么只要求出最大区间和判断是否大于d*k就可以了;

 线段树维护,复杂度O(mlogn);


代码:


#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 210000
#define lson l,mid,no<<1
#define rson mid+1,r,no<<1|1
using namespace std;
typedef long long ll;
struct Seg
{
	ll L,R,ma,sum;
	Seg(){}
	Seg(ll x){L=R=ma=sum=x;}
	friend Seg operator +(Seg l,Seg r)
	{
		Seg ret;
		ret.sum=l.sum+r.sum;
		ret.L=max(l.L,l.sum+r.L);
		ret.R=max(r.R,r.sum+l.R);
		ret.ma=max(l.R+r.L,max(l.ma,r.ma));
		return ret;
	}
}tr[N<<2];
void Pushup(ll no)
{
	tr[no]=tr[no<<1]+tr[no<<1|1];
}
void Build(ll l,ll r,ll no,ll k)
{
	if(l==r)
		tr[no]=Seg(-k);
	else
	{
		ll mid=l+r>>1;
		Build(lson,k);
		Build(rson,k);
		Pushup(no);
	}
}
void update(ll l,ll r,ll no,ll x,ll val)
{
	if(l==r)
		tr[no]=Seg(tr[no].sum+val);
	else
	{
		ll mid=l+r>>1;
		if(x<=mid)	update(lson,x,val);
		else		update(rson,x,val);
		Pushup(no);
	}
}
int main()
{
	ll n,m,d,i,j,k,x,r;
	scanf("%lld%lld%lld%lld",&n,&m,&k,&d);
	Build(1,n,1,k);
	for(i=1;i<=m;i++)
	{
		scanf("%lld%lld",&r,&x);
		update(1,n,1,r,x);
		if(tr[1].ma>(ll)d*k)
			puts("NIE");
		else
			puts("TAK");
	}
	return 0;
}



bzoj-1135 Lyz

标签:bzoj   poi   线段树   二分图   

原文地址:http://blog.csdn.net/ww140142/article/details/48516667

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!