【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;
}
原文地址:https://www.cnblogs.com/iwtwiioi/p/4985664.html