【BZOJ】1135: [POI2009]Lyz

题意

\(1\)\(n(1 \le n \le 200000)\)号的溜冰鞋各\(k(1 \le k \le 10^9)\)双。已知\(x\)号脚的人可以穿\(x\)\(x+d\)的溜冰鞋。
\(m(1 \le m \le 500000)\)次操作,每次来了\(x_i\)\(r_i\)号脚的人。\(x_i\)为负,则代表走了这么多人。对于每次操作,输出溜冰鞋是否足够。

分析

容易发现是二分图模型,然而数据太大。

题解

根据Hall定理:如果存在\(X\)的完备匹配,则\(X\)中任意\(k\)个点都至少与\(Y\)中的\(k\)个点相邻。
所以我们只需要在任意一些人使得满足这个条件那么就行了。
然后来了个神结论:
假设\(a_i\)\(i\)号鞋的人,则只要任意的\([l, r]\)满足\(\sum_{i=l}^{r} a_i \ge (r-l+1+d) * k\),即\(\sum_{i=l}^{r} (a_i-k) \ge d * k\)则可行。
并不知道这个结论怎么来的...
所以用线段树维护一下最大子序列的值即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int getint() {
	int x=0, f=1, c=getchar();
	for(; c<48||c>57; f=c=='-'?-1:f, c=getchar());
	for(; c>47&&c<58; x=x*10+c-48, c=getchar());
	return x*f;
}
struct T {
	ll mx, mxl, mxr, s;
	void init() {
		mx=mxl=mxr=s;
	}
}t[1000005];
int n, m, k, d;
void up(int x) {
	int l=x<<1, r=x<<1|1;
	t[x].s=t[l].s+t[r].s;
	t[x].mxl=max(t[l].mxl, t[l].s+t[r].mxl);
	t[x].mxr=max(t[r].mxr, t[r].s+t[l].mxr);
	t[x].mx=max(t[l].mxr+t[r].mxl, max(t[l].mx, t[r].mx));
}
void upd(int p, int g, int l=1, int r=n, int x=1) {
	if(l==r) {
		t[x].s+=g;
		t[x].init();
		return;
	}
	int mid=(l+r)>>1;
	if(p<=mid) {
		upd(p, g, l, mid, x<<1);
	}
	else {
		upd(p, g, mid+1, r, x<<1|1);
	}
	up(x);
}
int main() {
	n=getint(), m=getint(), k=getint(), d=getint();
	for(int i=1; i<=n; ++i) {
		upd(i, -k);
	}
	for(ll te=(ll)d*k; m; --m) {
		int r=getint(), x=getint();
		upd(r, x);
		puts(t[1].mx<=te?"TAK":"NIE");
	}
	return 0;
}
posted @ 2015-11-22 13:17  iwtwiioi  阅读(520)  评论(0编辑  收藏  举报