版权声明:蒟蒻写的..能不能吱一声呀 https://blog.csdn.net/Rose_max/article/details/84582812
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
题解
是个二分图模型
可以 硬做,然后就T的飞起,然后就hall定理
Hall定理
如果一个二分图存在完备匹配
设起较小的集合为X,较大的为Y。则在X中任选K个点,都会找到至少K个点与他们相连(并集)
考虑如何判断,直接枚举是 的
要一点贪心
鞋码为x的人看作一个集合,显然这个集合的点,要不都选或者要不都不选
因为他萌连的点是一样的,选了一个的时候你肯定想让这个K尽量大然后让fail的可能变大
然后就可以变成选一些集合
深入挖掘一下,如果选了集合a,如果还要选下一个集合才能让这个fail,这个集合肯定与a相邻
因为如果选其他集合,要不就是与当前连了的范围没有交集,这样如果要选那个集合的话其实之前的集合都不用选的…
有交集的话肯定就是想让交集的补集尽量小了
所以选的都是相邻的
那么就可以变成一个柿子
划一下就可以变成
然后就是个最大子段和
线段树即可
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define lc now<<1
#define rc now<<1|1
using namespace std;
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int stack[20];
inline void write(int x)
{
if(!x){putchar('0');return;}
int top=0;
while(x)stack[++top]=x%10,x/=10;
while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);printf(" ");}
inline void pr2(int x){write(x);puts("");}
LL mx[210000*4],l1[210000*4],r1[210000*4],sum[210000*4];
void pushup(int now)
{
mx[now]=max(max(mx[lc],mx[rc]),r1[lc]+l1[rc]);
l1[now]=max(l1[lc],sum[lc]+l1[rc]);
r1[now]=max(r1[rc],sum[rc]+r1[lc]);
sum[now]=sum[lc]+sum[rc];
}
void modify(int now,int l,int r,int p,LL c)
{
if(l==r)
{
mx[now]+=c;l1[now]+=c;r1[now]+=c;sum[now]+=c;
return ;
}
int mid=(l+r)/2;
if(p<=mid)modify(lc,l,mid,p,c);
else modify(rc,mid+1,r,p,c);
pushup(now);
}
int n,m,K,D;
int main()
{
n=read();m=read();K=read();D=read();
for(int i=1;i<=n;i++)modify(1,1,n,i,-K);
while(m--)
{
int x=read(),pa=read();
modify(1,1,n,x,pa);
if(mx[1]<=(LL)D*K)puts("TAK");
else puts("NIE");
}
return 0;
}