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;
}
posted @ 2018-07-11 18:55  ws_zzy  阅读(310)  评论(0编辑  收藏  举报