1135: [POI2009]Lyz

1135: [POI2009]Lyz

https://lydsy.com/JudgeOnline/problem.php?id=1135

分析:

  hall定理+线段树连续区间的最大的和。

  首先转化为二分图的模型,然后根据hall定理

Hall定理:

此定理使用于组合问题中,二部图G中的两部分顶点组成的集合分别为X, Y, X={X1, X2, X3,X4,.........,Xm}, Y={y1, y2, y3, y4 ,.........,yn},G中有一组无公共点的边,一端恰好为组成X的点的充分必要条件是:

X中的任意k个点至少与Y中的k个点相邻。(1≤k≤m) 

  那么如果直接枚举子集的话肯定不行,如果满足了最劣的情况,那么也就全满足了,所以考虑如何求出最劣的情况。

  假设当前有连续的k个人[l,r],他们对应的鞋子区间是[l,r+d],那么如果此时有l-1处有a[l-1]:如果a[l-1]>k,那么将l-1和[l,r]这些人数的区间合成[l-1,r]的时候,增加的人数大于鞋子的个数,一定比分开算劣,所以就合起来。否则a[l-1]<=k,合起来比现在优,那么就不合起来。

  所以最劣的情况就是对a[i]-k,求最大的子段和。

代码:    

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cmath>
 6 #include<cctype>
 7 #include<set>
 8 #include<queue>
 9 #include<vector>
10 #include<map>
11 using namespace std;
12 typedef long long LL;
13  
14 inline int read() {
15     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
16     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
17 }
18  
19 const int N = 200005;
20  
21 struct Node{
22     LL ls, rs, sum, mx;
23 }T[N << 2];
24 LL a[N];
25  
26 void pushup(int rt) {
27     T[rt].ls = max(T[rt << 1].ls, T[rt << 1].sum + T[rt << 1 | 1].ls);
28     T[rt].rs = max(T[rt << 1 | 1].rs, T[rt << 1 | 1].sum + T[rt << 1].rs);
29     T[rt].sum = T[rt << 1].sum + T[rt << 1 | 1].sum;
30     T[rt].mx = max(T[rt << 1].rs + T[rt << 1 | 1].ls, max(T[rt << 1].mx, T[rt << 1 | 1].mx));
31 }
32 void update(int l,int r,int rt,int p,LL x) { // LL x !!!
33     if (l == r) {
34         T[rt].ls = T[rt].rs = T[rt].sum = T[rt].mx = x; return ;
35     }
36     int mid = (l + r) >> 1;
37     if (p <= mid) update(l, mid, rt << 1, p, x);
38     else update(mid + 1, r, rt << 1 | 1, p, x);
39     pushup(rt);
40 }
41 int main() {
42     int n = read(), m = read(); LL k = read(), d = read(), mx = d * k; 
43     n -= d;
44     for (int i = 1; i <= n; ++i) update(1, n, 1, i, -k); 
45     while (m --) {
46         int p = read(), x = read();
47         a[p] = a[p] + x;
48         update(1, n, 1, p, a[p] - k);
49         puts(T[1].mx <= mx ? "TAK" : "NIE");
50     }
51     return 0;
52 }
原文地址:https://www.cnblogs.com/mjtcn/p/10055061.html