zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    访问修饰符的权限。
    字符编码
    3/11 作业
    3/10 作业
    作业 3/9
    流程控制之for循环
    Exception in createBlockOutputStream
    windows上传文件到 linux的hdfs
    win10 配置 hadoop-2.7.2
    hadoop 源码编译
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10055061.html
Copyright © 2011-2022 走看看