zoukankan      html  css  js  c++  java
  • $bzoj1135$

    $Hall定理+线段树$

    $Hall定理:对于有完美匹配的二分图,从全部匹配的那一侧选择k个元素,另一侧至少有k个元素与其相连,这里指的是元素的并集,这个是充要条件,也就是我们可以用这个条件判断二分图是否有完美匹配,这里就用到了。完美匹配就是指全部匹配了$

    $题目里人和鞋构成二分图,要求人有完美匹配,那么我们运用Hall定理,只要任意选出k个人相邻的鞋至少有k双就行了,但是如果直接枚举的话复杂度是指数级的$

    $观察一下发现,事实上如果任意连续的一段人满足了,那么不连续的肯定满足,因为每个人对应的鞋是[x,x+k],那么对于一段连续的人我们挖掉中间的一个人不会让对应的鞋的集合变小,所以我们只用看连续的人就可以了,用线段树检查,但是复杂度是O(n^{2}logn)的$

    $继续观察,事实上可以化简成这样的一个式子sum_{i=l}^{r}{a[i]}leq{(r-l+k+1)*d}$

    $然后就很简单了,相当于sum_{i=l}^{r}{a[i]-k}leq{k*d}$

    $由于k*d是定值,那么我们用线段树维护左边的式子,查询最大子段和就行了$

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 2e5 + 5;
    int n, m, k, d;
    ll l[N << 2], r[N << 2], sum[N << 2], mx[N << 2];
    void update(int L, int R, int x, int p, int d) {
        if(L == R) {
            mx[x] += d;
            sum[x] += d;
            l[x] += d;
            r[x] += d;
            return;
        }
        int mid = (L + R) >> 1;
        if(p <= mid) {
            update(L, mid, x << 1, p, d);
        } else {
            update(mid + 1, R, x << 1 | 1, p, d);
        }
        sum[x] = sum[x << 1] + sum[x << 1 | 1];
        l[x] = max(l[x << 1], sum[x << 1] + l[x << 1 | 1]);
        r[x] = max(r[x << 1 | 1], sum[x << 1 | 1] + r[x << 1]);
        mx[x] = max(mx[x << 1], max(mx[x << 1 | 1], r[x << 1] + l[x << 1 | 1]));
    }
    void build(int L, int R, int x) {
        if(L == R) {
            mx[x] = l[x] = r[x] = sum[x] = -k;
            return;
        }
        int mid = (L + R) >> 1;
        build(L, mid, x << 1);
        build(mid + 1, R, x << 1 | 1);
        sum[x] = sum[x << 1] + sum[x << 1 | 1];
        l[x] = max(l[x << 1], sum[x << 1] + l[x << 1 | 1]);
        r[x] = max(r[x << 1 | 1], sum[x << 1 | 1] + r[x << 1]);
        mx[x] = max(mx[x << 1], max(mx[x << 1 | 1], r[x << 1] + l[x << 1 | 1]));
    }
    int main() {
        scanf("%d%d%d%d", &n, &m, &k, &d);
        build(1, n, 1);
        while(m--) {
            int r, x;
            scanf("%d%d", &r, &x);
            update(1, n, 1, r, x);
            puts(mx[1] <= (ll)d * k ? "TAK" : "NIE");
        }
        return 0;
    } 
    View Code
  • 相关阅读:
    进阶系列(8)——匿名方法与lambda表达式
    进阶系列(3)—— 序列化与反序列化
    进阶系列(4)——扩展方法
    数据库设计开发规范
    .Net 项目代码风格
    用JS获取地址栏参数的方法(超级简单)
    Ajax轮询 select循环输出
    【Jquery】jquery刷新页面(局部及全页面刷新)
    网页上 滚动代码 最简单的
    eazyui 或bootstrap table表格里插入图片,点击查看大图
  • 原文地址:https://www.cnblogs.com/19992147orz/p/8367204.html
Copyright © 2011-2022 走看看