# Hall定理

$$X$$ 中的任意 $$k$$ 个点都至少与 $$Y$$ 中的 $$k$$ 个点相邻，与二分图存在完美匹配

## BZOJ 1135 [POI2009]Lyz

$$\sum_{i=l}^{r}x_{i}-k<=d \times k$$

$$x_{i}'=x_{i}-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;
}

posted @ 2018-07-11 18:55  ws_zzy  阅读(301)  评论(0编辑  收藏  举报