Hall定理
Hall定理
二分图 \(X-Y\),设 \(|X|<=|Y|\)
\(X\) 中的任意 \(k\) 个点都至少与 \(Y\) 中的 \(k\) 个点相邻,与二分图存在完美匹配
互为充要条件
证明:呵呵,不会
BZOJ 1135 [POI2009]Lyz
考虑最紧的限制,肯定是一段连续的人,因为这样他们相交的最多
那么也就是任意 \(l,r\),都有 \(\sum_{i=l}^{r}x_{i}<=(r-l+1+d)\times k\)
\(\sum_{i=l}^{r}x_{i}-k<=d \times k\)
令 \(x_{i}'=x_{i}-k\)
那么也就是最大子段\(<=d \times k\)
用线段树维护即可
#include<iostream>
#include<cstdio>
#include<cstring>
#define lo (now<<1)
#define ro ((now<<1)|1)
using namespace std;
const int maxn=200009;
int n,m,k,d;
long long limt;
struct SegmentTree{
int l,r;
long long sum,mx_l,mx_r,mx_sum;
}tree[maxn<<2];
void pushup(int now){
tree[now].sum=tree[lo].sum+tree[ro].sum;
tree[now].mx_l=max(tree[lo].mx_l,tree[lo].sum+tree[ro].mx_l);
tree[now].mx_r=max(tree[ro].mx_r,tree[ro].sum+tree[lo].mx_r);
tree[now].mx_sum=max(tree[lo].mx_r+tree[ro].mx_l,max(tree[lo].mx_sum,tree[ro].mx_sum));
}
void BuildTree(int now,int l,int r){
tree[now].l=l;tree[now].r=r;
tree[now].sum=tree[now].mx_l=tree[now].mx_r=tree[now].mx_sum=0;
if(l==r){
tree[now].sum=-k;
return;
}
int mid=(l+r)>>1;
BuildTree(lo,l,mid);
BuildTree(ro,mid+1,r);
pushup(now);
}
void updataPoint(int now,int pla,int tag){
if(tree[now].l==tree[now].r){
tree[now].sum+=tag;
tree[now].mx_l=tree[now].mx_r=tree[now].mx_sum=max(0LL,tree[now].sum);
return;
}
int mid=(tree[now].l+tree[now].r)>>1;
if(pla<=mid)updataPoint(lo,pla,tag);
else updataPoint(ro,pla,tag);
pushup(now);
}
int main(){
scanf("%d%d%d%d",&n,&m,&k,&d);
limt=1LL*k*d;
BuildTree(1,1,n-d);
while(m--){
int x,y;
scanf("%d%d",&x,&y);
updataPoint(1,x,y);
if(tree[1].mx_sum<=limt){
printf("TAK\n");
}else{
printf("NIE\n");
}
}
return 0;
}
致歉:笔者已经意识到这是一篇几乎没有价值的文章,给您的阅读带来不好的体验,并且干扰了您的搜索环境,非常抱歉!