• CF1452E Two Editorials【贪心】【差分】


    E. Two Editorials

    按中点将线段排序,枚举选择前几个人去听第一个老师的课,剩下的自然去到第二个老师。

    枚举两个老师选择的区间,每次统计当前选择的两部分人与此区间的重合区间和,维护差分前缀和。

    差分前缀和还要统计区间和,由于众所周知本人很懒,不想用一个数组倒腾,于是开了两个树状数组。时间复杂度$O(n^2logn)$,用一个数组乱搞也只是伪$n^2$,妹有意思。

    #include<bits/stdc++.h>
    using namespace std;
    
    int n, m, k;
    
    struct Node {
        int l, r;
    } stu[2005];
    
    bool cmp(Node a, Node b) {
        return (a.l + a.r) < (b.l + b.r);
    }
    
    int f[2005], las[2005], pre[2005], ini[2005];
    
    int tr1[2005];
    
    int lowbit(int x) {
        return x & (-x);
    }
    
    void add1(int pos, int d) {
        for(int i = pos; i <= n; i += lowbit(i))
            tr1[i] += d;
    }
    
    int query1(int pos) {
        int ans = 0;
        for(int i = pos; i; i -= lowbit(i))
            ans += tr1[i];
        return ans;
    }
    
    int tr2[2005];
    void add2(int pos, int d) {
        for(int i = pos; i <= n; i += lowbit(i))
            tr2[i] += d;
    }
    
    int query2(int pos) {
        int ans = 0;
        for(int i = pos; i; i -= lowbit(i))
            ans += tr2[i];
        return ans;
    }
    
    int main() {
        scanf("%d%d%d", &n, &m, &k);
        for(int i = 1; i <= m; i ++) {
            int a, b;
            scanf("%d%d", &a, &b);
            stu[i].l = a, stu[i].r = b;
            f[a] ++, f[b + 1] --;
        }
        sort(stu + 1, stu + m + 1, cmp);
        int ans = 0;
        for(int i = 1; i <= m; i ++) {
            ini[stu[i].l] ++, ini[stu[i].r + 1] --;
            int maxn = 0;
            memset(pre, 0, sizeof(pre));
            memset(tr1, 0, sizeof(tr1));
            for(int j = 1; j <= n; j ++) {
                pre[j] = pre[j - 1] + ini[j];
                add1(j, pre[j]);
                if(j >= k)    maxn = max(maxn, query1(j) - query1(j - k));
            }
            f[stu[i].l] --, f[stu[i].r + 1] ++;
            int maxm = 0;
            memset(las, 0, sizeof(las));
            memset(tr2, 0, sizeof(tr2));
            for(int j = 1; j <= n; j ++) {
                las[j] = las[j - 1] + f[j];
                add2(j, las[j]);
                if(j >= k)    maxm = max(maxm, query2(j) - query2(j - k));
            }
            ans = max(ans, maxm + maxn);
        }
        printf("%d", ans);
        return 0;
    }

    这道题是夜宵前大佬们累了俺想出来的耶!

  • 相关阅读:
    Balsamiq Mockups完全手册[转]
    如何成为一个专家
    [ 转]discuz 的加密与解密函数authcode解析
    无题
    [转]Yahoo!网站性能最佳体验的34条黄金守则——内容
    唐僧的家书
    Webservice超时问题
    c#类的初始化顺序
    智力逻辑题程序实现(生日猜测)
    Winform下重写Button按钮
  • 原文地址:https://www.cnblogs.com/wans-caesar-02111007/p/14057350.html
Copyright © 2020-2023  润新知