• 省队集训 Day5 选举


    【题目大意】

    小奇和魔法猪要竞选膜钟国的总统。

    有 $n$ 个选民,编号为$1...n$,他们中有的人支持小奇,有的人支持魔法猪,还有的人保持中立。

    现在你需要把选民分成若干个区间,每个区间的长度在$[l,r]$中。如果一个区间中支持小奇的人比支持魔法猪的人多,那么小奇得一票,一个区间中支持魔法猪的人比支持小奇的人多,那么魔法猪得一票。

    小奇想要赢得选举,于是它请你合理地分区间,使得它获得的票数减去魔法猪获得的票数最大。如果你帮它解决了这个问题,它会送你这道题的题解。

    $n leq 10^6$

    【题解】

    考虑暴力dp,复杂度为$O(n^2)$。

    然后考虑优化暴力,每次相当于区间往右移动一格,相当于加入1个数,减去1个数,这个可以用线段树来维护

    如果普通写法需要开单调队列,我们可以把下标映射到位置,这样就能执行减去1个数的操作了。

    复杂度$O(nlogn)$

    # include <vector>
    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    typedef long double ld;
    
    const int M = 5e5 + 10, N = 1e6 + 10, inf = 1e9, SN = 1024 * 1024 + 5;
    
    inline int getint() {
        int x = 0, f = 1; char ch = getchar();
        while(!isdigit(ch)) {
            if(ch == '-') f = 0;
            ch = getchar();
        }
        while(isdigit(ch)) x = (x<<3) + (x<<1) + ch - '0', ch = getchar();
        return f ? x : -x;
    }
    
    int n, L, R, a[N], s[N], f[N], pos[N], idx;
    vector<int> v[N + N]; int l[N], r[N];
    
    struct SMT {
        int w[N << 2];
        # define ls (x<<1)
        # define rs (x<<1|1)
        inline void up(int x) {
            w[x] = max(w[ls], w[rs]);
        }
        inline void build(int x, int l, int r) {
            w[x] = -inf;
            if(l == r) return ;
            int mid = l+r>>1;
            build(ls, l, mid); build(rs, mid+1, r);
        }
        inline void edt(int x, int l, int r, int pos, int del) {
            if(l == r) {
                w[x] = del;
                return ;
            }
            int mid = l+r>>1;
            if(pos <= mid) edt(ls, l, mid, pos, del);
            else edt(rs, mid+1, r, pos, del);
            up(x);
        }
        inline int query(int x, int l, int r, int L, int R) {
            if(L > R) return -inf;
            if(L <= l && r <= R) return w[x];
            int mid = l+r>>1;
            if(R <= mid) return query(ls, l, mid, L, R);
            else if(L > mid) return query(rs, mid+1, r, L, R);
            else return max(query(ls, l, mid, L, mid), query(rs, mid+1, r, mid+1, R));
        }
        # undef ls
        # undef rs
    }T;
    
    inline void ins(int i) {
    //    cout << "add " << pos[i] << endl;
        T.edt(1, 0, n, pos[i], f[i]);
    }
    
    inline void del(int i) {
        T.edt(1, 0, n, pos[i], -inf);
    }
    
    int main() {
        freopen("election.in", "r", stdin);
        freopen("election.out", "w", stdout);
        n = getint(), L = getint(), R = getint();
        for (int i=1; i<=n; ++i) a[i] = getint();
        for (int i=1; i<=n; ++i) s[i] = s[i-1] + a[i];
    //    for (int i=0; i<=n; ++i) cout << s[i] << ' '; cout << endl;
        
        for (int i=0; i<=n; ++i) v[s[i] + n].push_back(i);
        for (int i=0; i<=n+n; ++i) {
            int lst = idx;
            for (int j=0; j<v[i].size(); ++j) 
                pos[v[i][j]] = idx++;
            for (int j=0; j<v[i].size(); ++j)
                l[v[i][j]] = lst, r[v[i][j]] = idx - 1;
        }
    //    for (int i=0; i<=n; ++i) cout << pos[i] << ' ' << l[i] << ' ' << r[i] << endl; cout << endl;
        
        f[0] = 0;
        T.build(1, 0, n);
        for (int i=1; i<=n; ++i) {
            if(i - R - 1 >= 0) del(i - R - 1);
            if(i - L >= 0) ins(i - L);
            int ta = T.query(1, 0, n, 0, l[i]-1), tb = T.query(1, 0, n, r[i]+1, n), tc = T.query(1, 0, n, l[i], r[i]);
            if(ta != -inf) ta ++;
            if(tb != -inf) tb --;
    //        cout << i << "???" << l[i]-1 <<endl;
    //        cout << i << ' ' << ta << ' ' << tb << ' ' << tc << endl;
            f[i] = max(ta, max(tb, tc));
        }
            
    //    }
        if(f[n] == -inf) cout << "Impossible";
        else cout << f[n];
        return 0;
    }
    View Code
  • 相关阅读:
    python获取当前路径
    python的StringIO
    python判断两个文件是否相同
    Linux查找文件内容
    python日志syslog运用
    python获取当前运行程序的名字
    python连接Linux命令行
    python预编译函数compile,exec,eval
    python日志模块
    Scala安装教程
  • 原文地址:https://www.cnblogs.com/galaxies/p/20170711_a.html
Copyright © 2020-2023  润新知