zoukankan      html  css  js  c++  java
  • BZOJ2006 超级钢琴

    Description

    ​ 给定一个长度为n的区间,询问前k大的区间和,区间长度(in [L, R])。 $ n, k <= 500000$

    Solution

    ​ 首先求前缀和。把一个区间拆成两个前缀和之差。

    ​ 对于一个固定的右端点。我们首先需要最小化左端点。那么我们就在题目条件允许的范围内先求出左端点最小的位置, 但是一个区间的次大值可能超过别的区间的最大值, 这很麻烦。

    ​ 开一个堆, 维护一个三元组(Pos, Kth, Val), 表示以Pos为右端点,本次查到区间第Kth大,值为Val。

    ​ 然后把一个区间从堆中取出来时, 就把他的(Pos, Kth + 1, Val_)加入堆。

    ​ 然后只要取k次即可。

    ​ 时间复杂度(O((n + k)log_{2}^{n}))

    反思

    ​ 刚刚开始想到把每个右端点的左端点按照大小都加进小根堆, 小根堆大小为K,如果超过就弹出一个。 如果当前值小于堆顶就break, 然后就被卡T到8s

    ​ 最后发现,其实你并不需要把全部的都加入堆,因为只要当前的区间被弹出,才有可能用他的次大值。

    ​ 所以我们只要贪心取最大值就可以的。

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i, a, b) for(int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
    #define drep(i, a, b) for(int i = (a), i##_end_ = (b); i >= i##_end_; --i)
    #define clar(a, b) memset((a), (b), sizeof(a))
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    #define Debug(s) debug("The massage in line %d, Function %s: %s
    ", __LINE__, __FUNCTION__, s)
    typedef long long LL;
    typedef long double LD;
    const int BUF_SIZE = (int)1e6 + 10;
    struct fastIO {
        char buf[BUF_SIZE], buf1[BUF_SIZE];
        int cur, cur1;
        FILE *in, *out;
        fastIO() {
            cur = BUF_SIZE, in = stdin, out = stdout;
    		cur1 = 0;
        }
        inline char getchar() {
            if(cur == BUF_SIZE) fread(buf, BUF_SIZE, 1, in), cur = 0;
            return *(buf + (cur++));
        }
        inline void putchar(char ch) {
            *(buf1 + (cur1++)) = ch;
            if (cur1 == BUF_SIZE) fwrite(buf1, BUF_SIZE, 1, out), cur1 = 0;
        }
        inline int flush() {
            if (cur1 > 0) fwrite(buf1, cur1, 1, out);
            return cur1 = 0;
        }
    }IO;
    #define getchar IO.getchar
    #define putchar IO.putchar
    int read() {
    	char ch = getchar();
    	int x = 0, flag = 1;
    	for(;!isdigit(ch); ch = getchar()) if(ch == '-') flag *= -1;
    	for(;isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
    	return x * flag;
    }
    void write(int x) {
    	if(x < 0) putchar('-'), x = -x;
    	if(x >= 10) write(x / 10);
    	putchar(x % 10 + 48);
    }
    void putString(char s[], char EndChar = '
    ') {
    	rep(i, 0, strlen(s) - 1) putchar(*(s + i));
    	if(~EndChar) putchar(EndChar);
    }
    
    #define Maxn 500009
    int n, k, L, R, a[Maxn];
    LL s[Maxn];
    template <typename T, int (*Cmp)(T a, T b)> struct Heap {
    	T a[Maxn];
    	int len; 
    	void push(T val) {
    		a[++len] = val;
    		push_heap(a + 1, a + len + 1, Cmp);
    	}
    	T pop() { pop_heap(a + 1, a + len + 1, Cmp); return a[len--];}
    	T top() {return a[1];}
    	T empty() { return !len;}
    };
    LL W[Maxn], d, Ns[Maxn];
    namespace Chairman {
    	int t[Maxn * 64], lc[Maxn * 64], rc[Maxn * 64], amt, rt[Maxn];
    	int build(int l, int r) {
    		int u = ++amt, mid = (l + r) >> 1;
    		if(l == r) return u;
    		lc[u] = build(l, mid);
    		rc[u] = build(mid + 1, r);
    		return u;
    	}
    	int modify(int rt, int l, int r, int pos) {
    		int mid = (l + r) >> 1, u = ++amt;
    		t[u] = t[rt] + 1; lc[u] = lc[rt], rc[u] = rc[rt];
    		if(l == r) return u;
    		(pos <= mid) ? (lc[u] = modify(lc[rt], l, mid, pos)) : (rc[u] = modify(rc[rt], mid + 1, r, pos));
    		return u;
    	}
    	int query(int rt0, int rt1, int l, int r, int pos) {
    		if(l == r) return l;
    /**/	int res = t[lc[rt1]] - t[lc[rt0]], mid = (l + r) >> 1;
    		return (res >= pos) ? (query(lc[rt0], lc[rt1], l, mid, pos)) : (query(rc[rt0], rc[rt1], mid + 1, r, pos - res));
    	}
    }
    namespace INIT {
    	void Main() {
    		n = read(), k = read(); L = read(), R = read();
    		rep(i, 1, n) a[i] = read(), W[i + 1] = (s[i] = s[i - 1] + a[i]);
    		sort(W + 1, W + n + 2);
    		d = unique(W + 1, W + n + 2) - W - 1;
    		rep(i, 0, n) Ns[i] = lower_bound(W + 1, W + d + 1, s[i]) - W;
    	}
    }
    namespace SOLVE {
    	using namespace Chairman;
    	struct node {
    		int pos, kth;
    		LL val;
    	};
    	int cmp(node tarA, node tarB) { return tarA.val < tarB.val;}
    	Heap <node, cmp> hep;
    	void Main() {
    		rt[0] = build(1, d), rt[1] = modify(rt[0], 1, d, Ns[0]);
    		rep(i, 1, n) rt[i + 1] = modify(rt[i], 1, d, Ns[i]);
    		rep(i, 1, n) {
    			int bound1 = max(i - R, 0), bound2 = i - L;
    			if(bound2 < bound1) continue;
    			int cur = query(rt[bound1], rt[bound2 + 1], 1, d, 1);
    			hep.push((node){i, 1, s[i] - W[cur]});
    		}
    		LL ans = 0;
    		rep(i, 1, k) {
    			node Tmp = hep.pop();
    			ans += Tmp.val;
    			int bound1 = max(Tmp.pos - R, 0), bound2 = Tmp.pos - L;
    			if(Tmp.kth + 1 > bound2 - bound1 + 1) continue;
    			int cur = query(rt[bound1], rt[bound2 + 1], 1, d, Tmp.kth + 1);
    			hep.push((node){Tmp.pos, Tmp.kth + 1, s[Tmp.pos] - W[cur]});
    		}
    		cout << ans << endl;
    	}
    }
    int main() {
    #ifdef Qrsikno
    	freopen("BZOJ2006.in", "r", stdin);
    	freopen("BZOJ2006.out", "w", stdout);
    #endif
    	INIT :: Main();
    	SOLVE :: Main();
    #ifdef Qrsikno
    	debug("
    Running time: %.3lf(s)
    ", clock() * 1.0 / CLOCKS_PER_SEC);
    #endif
    	return IO.flush();
    }
    
    

  • 相关阅读:
    WPF DelegateCommand 出现Specified cast is not valid
    WPF DelegateCommand 出现Specified cast is not valid
    WPF DelegateCommand 出现Specified cast is not valid
    win10 sdk 是否向下兼容
    win10 sdk 是否向下兼容
    win10 sdk 是否向下兼容
    PHP extract() 函数
    PHP end() 函数
    PHP each() 函数
    PHP current() 函数
  • 原文地址:https://www.cnblogs.com/qrsikno/p/9732751.html
Copyright © 2011-2022 走看看