zoukankan      html  css  js  c++  java
  • 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
    ", ans);
    }
    
    int main() {
    	n = read(); k = read();
    	rep(i, 1, n) a[i] = read();
    	wish_upon_to_the_star();
    	return 0;
    }
    
  • 相关阅读:
    转 JQuery 爱好者们的福音:jQuery EasyUI 开源插件套装 完全替代ExtJS 武胜
    转 自己做的C#版ILMerge,可将所有引用的DLL和exe文件打成一个exe文件,有图解 武胜
    关于文件结束符EOF feof 区别
    OpenLDAP中文版帮助文件(转)
    文件结束符EOF .
    VMware中Linux系统网络配置
    Python 字符串格式化输出(format/printf)
    李彦宏创业12年解读:企业家精神改变工程师命运
    gcc命令行详解
    如何成为一名 Google 软件工程师?
  • 原文地址:https://www.cnblogs.com/reverymoon/p/10068300.html
Copyright © 2011-2022 走看看