hihocoder#1046 K个串 可持久化线段树 + 堆


首先考虑二分,然后发现不可行....

注意到\(k\)十分小,尝试从这里突破

首先用扫描线来处理出以每个节点为右端点的区间的权值和,用可持久化线段树存下来

在所有的右端点相同的区间中,挑一个权值最大的,放入堆中

每次从堆中取出最大元素,然后从被删除的右端点区间中选一个次大的区间

重复\(k\)次即可

复杂度\(O(n \log n + k \log n)\)


\(A\)开心

#include <map>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

#define ll long long
#define ri register int
#define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
#define drep(io, ed, st) for(ri io = ed; io >= st; io --)

#define gc getchar
inline int read() {
	int p = 0, w = 1; char c = gc();
	while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
	while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
	return p * w;
}
	
const int sid = 1e5 + 5;
const int eid = 2e7 + 5;
	
int n, k, id, a[sid], rt[sid];
map <int, int> lst;

ll tag[eid];
int ls[eid], rs[eid];

struct ym {
	ll max; int maxp;
	friend bool operator < (ym a, ym b)
	{ return a.max < b.max; }
} t[eid];

priority_queue < pair <ym, int> > q;

inline int newnode(int pre) {
	++ id; 
	if(pre) t[id] = t[pre]; tag[id] = tag[pre];
	ls[id] = ls[pre]; rs[id] = rs[pre];
	return id;
}

inline void mdf(int &o, int p, int l, int r, int ml, int mr, ll v) {
	o = newnode(p);
	if(ml <= l && mr >= r) {
		tag[o] += v;
		t[o].max += v;
		if(l == r) t[o].maxp = l;
		return;
	}
	int mid = (l + r) >> 1;
	if(ml <= mid) mdf(ls[o], ls[p], l, mid, ml, mr, v);
	if(mr > mid) mdf(rs[o], rs[p], mid + 1, r, ml, mr, v);
	t[o] = max(t[ls[o]], t[rs[o]]); t[o].max += tag[o];
}

void wish_upon_to_the_star() {
	t[0].max = -1e16;
	rep(i, 1, n) {
		mdf(rt[i], rt[i - 1], 1, n, i, i, 0);
		mdf(rt[i], rt[i], 1, n, lst[a[i]] + 1, i, a[i]);
		lst[a[i]] = i;
		q.push(make_pair(t[rt[i]], i));
	}
	ll ans = 0;
	while(k --) {
		ym tmp = q.top().first; 
		int id = tmp.maxp, pos = q.top().second;
		q.pop(); ans = tmp.max;
		mdf(rt[pos], rt[pos], 1, n, id, id, -1e16);
		q.push(make_pair(t[rt[pos]], pos));
	}
	printf("%lld\n", ans);
}

int main() {
	n = read(); k = read();
	rep(i, 1, n) a[i] = read();
	wish_upon_to_the_star();
	return 0;
}
posted @ 2018-12-04 23:16  remoon  阅读(284)  评论(0编辑  收藏  举报