zoukankan      html  css  js  c++  java
  • BZOJ 4504: K个串

    题目大意:

    求一个序列的第k大的子串和。

    题解:

    对于一个右端点找最优的左端点,扔进堆里。

    每次取堆顶,将这个右端点可以选择的左端点的区间分成两段,扔进堆里,重复k次。

    现在需要对于一个固定的右端点,左端点在一个区间里,求最大值。

    可持久化线段树上区间修改,不用标记永久化也可以过。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<map>
    #include<queue>
    #define mp make_pair
    #define pr pair<long long,int>
    #define prr pair<pr,pr>
    #define fr first
    #define sc second
    using namespace std;
    int n,k,cnt,ls[10000005],rs[10000005],root[200005];
    long long tag[10000005];
    priority_queue<prr> q;
    map<int,int> pre;
    struct node{
    	long long val;
    	int id;
    }tree[10000005];
    void build(int &x,int l,int r){
    	x=++cnt;
    	tree[x]=(node){0,l};
    	if (l==r) return;
    	int mid=(l+r)>>1;
    	build(ls[x],l,mid);
    	build(rs[x],mid+1,r);
    }
    void add(int &now,int pre,long long key){
    	now=++cnt;
    	ls[now]=ls[pre],rs[now]=rs[pre],tree[now]=tree[pre],tag[now]=tag[pre]+key;
    	tree[now].val+=key;
    }
    void push_down(int x){
    	if (!tag[x]) return;
    	add(ls[x],ls[x],tag[x]);
    	add(rs[x],rs[x],tag[x]);
    	tag[x]=0;
    }
    void insert(int &now,int pre,int l,int r,int x,int y,int key){
    	if (l>y || r<x) return;
    	if (l>=x && r<=y){
    		add(now,pre,key);
    		return;
    	}
    	push_down(pre);
    	now=++cnt;
    	ls[now]=ls[pre],rs[now]=rs[pre],tree[now]=tree[pre];
    	int mid=(l+r)>>1;
    	insert(ls[now],ls[pre],l,mid,x,y,key);
    	insert(rs[now],rs[pre],mid+1,r,x,y,key);
    	if (tree[rs[now]].val>tree[ls[now]].val) tree[now]=tree[rs[now]];
    	else tree[now]=tree[ls[now]];
    }
    node query(int now,int l,int r,int x,int y){
    	if (!now) return (node){-1ll<<60,0};
    	if (l>y || r<x) return (node){-1ll<<60,0};
    	if (l>=x && r<=y) return tree[now];
    	push_down(now);
    	int mid=(l+r)>>1;
    	node max1=query(ls[now],l,mid,x,y);
    	node max2=query(rs[now],mid+1,r,x,y);
    	if (max1.val>max2.val) return max1;
    	else return max2;
    }
    void insert(int x,int l,int r){
    	if (l>r) return;
    	node sum=query(x,1,n,l,r);
    	q.push(mp(mp(sum.val,x),mp(l,r)));
    }
    int main(){
    	scanf("%d%d",&n,&k);
    	build(root[0],1,n);
    	for (int i=1; i<=n; i++){
    		int x;
    		scanf("%d",&x);
    		insert(root[i],root[i-1],1,n,pre[x]+1,i,x);
    		pre[x]=i;
    		insert(root[i],1,i);
    	}
    	long long sum;
    	while (k--){
    		sum=q.top().fr.fr;
    		int id=q.top().fr.sc,l=q.top().sc.fr,r=q.top().sc.sc;
    		q.pop();
    		int mid=query(id,1,n,l,r).id;
    		insert(id,l,mid-1);
    		insert(id,mid+1,r);
    	}
    	printf("%lld
    ",sum);
    	return 0;
    }
    

      

     

  • 相关阅读:
    Python元组、列表、字典
    测试通过Word直接发布博文
    Python环境搭建(windows)
    hdu 4003 Find Metal Mineral 树形DP
    poj 1986 Distance Queries LCA
    poj 1470 Closest Common Ancestors LCA
    poj 1330 Nearest Common Ancestors LCA
    hdu 3046 Pleasant sheep and big big wolf 最小割
    poj 3281 Dining 最大流
    zoj 2760 How Many Shortest Path 最大流
  • 原文地址:https://www.cnblogs.com/silenty/p/8760876.html
Copyright © 2011-2022 走看看