1135: [POI2009]Lyz

1135: [POI2009]Lyz

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 418   Solved: 191
[ Submit][ Status][ Discuss]

Description

初始时滑冰俱乐部有1到n号的溜冰鞋各k双。已知x号脚的人可以穿x到x+d的溜冰鞋。 有m次操作,每次包含两个数ri,xi代表来了xi个ri号脚的人。xi为负,则代表走了这么多人。 对于每次操作,输出溜冰鞋是否足够。

Input

n m k d ( 1≤n≤200,000 , 1≤m≤500,000 , 1≤k≤10^9 , 0≤d≤n ) ri xi ( 1≤i≤m, 1≤ri≤n-d , |xi|≤10^9 )

Output

对于每个操作,输出一行,TAK表示够 NIE表示不够。

Sample Input

4 4 2 1
1 3
2 3
3 3
2 -1

Sample Output

TAK
TAK
NIE
TAK

HINT

Source

[ Submit][ Status][ Discuss]



Hall定理,,,

把俱乐部的人看做点集X,溜冰鞋看做点集Y

显然这是一个二部图

根据Hall定理,如果存在饱和点集X的匹配,那么⊆ X,|N(S)| >= |S|

N(S)是Y中与X相邻的点的集合

对于此题,Hall定理最容易取到反例的状况一定是连续一段区间

因为此时能用来容纳X匹配的对应的Y总不多于不连续的区间

那么就是说,∀∑ai <= (r - l + 1 + d)*k,  (i∈[l,r])

两边同时-k,得∑(ai-k) <= d*k

于是,我们只需要维护连续序列的最大值就行了

线段树解决

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn = 2E5 + 20;
const int T = 4;
typedef long long LL;

int n,m;
LL k,d,c[maxn*T],ml[maxn*T],mr[maxn*T],ma[maxn*T];

void maintain(int o)
{
	int lc = (o<<1),rc = (o<<1|1);
	c[o] = c[lc] + c[rc];
	ma[o] = max(ma[lc],ma[rc]);
	ma[o] = max(ma[o],mr[lc] + ml[rc]);
	ml[o] = max(ml[lc],c[lc] + ml[rc]);
	mr[o] = max(mr[rc],c[rc] + mr[lc]);
}

void Build(int o,int l,int r)
{
	if (l == r) {
		c[o] = ma[o] = ml[o] = mr[o] = -k;
		return;
	}
	int mid = (l + r) >> 1;
	Build(o<<1,l,mid); 
	Build(o<<1|1,mid+1,r);
	maintain(o);
}

void Modify(int o,int l,int r,int pos,LL x)
{
	if (l == r) {
		c[o] += x; ma[o] += x;
		ml[o] += x; mr[o] += x;
		return;
	} 
	int mid = (l + r) >> 1;
	if(pos <= mid) Modify(o<<1,l,mid,pos,x);
	else Modify(o<<1|1,mid+1,r,pos,x);
	maintain(o);
}

int main()
{
	#ifdef DMC
		freopen("DMC.txt","r",stdin);
	#endif
	
	cin >> n >> m >> k >> d;
	Build(1,1,n);
	while (m--) {
		int r,x; scanf("%d%d",&r,&x);
		Modify(1,1,n,r,x);
		if (ma[1] > k*d) puts("NIE");
		else puts("TAK");
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值