zoukankan      html  css  js  c++  java
  • bzoj 4504: K个串【大根堆+主席树】

    像超级钢琴一样把五元组放进大根堆,每次取一个出来拆开,(d,l,r,p,v)表示右端点为d,左端点区间为(l,r),最大区间和值为v左端点在p上
    关于怎么快速求区间和,用可持久化线段树维护(主席树?)每个点到他root的区间和,这样每次右端点右移就是上一个的线段树在(la[a[i]]+1,i)加上a[i],la是这个值a[i]上一次出现的位置
    然后就可以在线处理询问了
    有一点因为这个线段树建的是1~n,所以右端点不是n的时候取max会取到右端点向右还是初始值0的位置(有可能前面是负数),这样的解决方法就是先全填成-inf,然后每次右移的时候先把右端点加上inf再处理区间加

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<map>
    #include<queue>
    using namespace std;
    const int N=300005;
    int n,m,has,rt[N],tot,la[N];
    long long a[N],g[N],rl[N],ans;
    map<long long ,int>mp;
    struct zxs
    {
    	int ls,rs,p;
    	long long mx,lz;
    }t[7000005];
    struct qwe
    {
    	int d,l,r,p;
    	long long v;
    	qwe(int D=0,int L=0,int R=0,int P=0,long long V=0)
    	{
    		d=D,l=L,r=R,p=P,v=V;
    	}
    	bool operator < (const qwe &a) const
    	{
    		return v<a.v;
    	}
    };
    priority_queue<qwe>q;
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    void build(int &ro,int l,int r)
    {
    	ro=++tot;
    	t[ro].p=l,t[ro].mx=-1e15;
    	if(l==r)
    		return;
    	int mid=(l+r)>>1;
    	build(t[ro].ls,l,mid);
    	build(t[ro].rs,mid+1,r);
    }
    void ud(int ro)
    {
    	if(t[t[ro].ls].mx>t[t[ro].rs].mx)
    		t[ro].mx=t[t[ro].ls].mx,t[ro].p=t[t[ro].ls].p;
    	else
    		t[ro].mx=t[t[ro].rs].mx,t[ro].p=t[t[ro].rs].p;
    }
    void update(int &ro,int la,int l,int r,int ll,int rr,long long v,long long lz)
    {
    	ro=++tot;
    	t[ro]=t[la];
    	t[ro].lz+=lz;
    	t[ro].mx+=lz;
    	if(l==ll&&r==rr)
    	{
    		t[ro].lz+=v;
    		t[ro].mx+=v;
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(t[ro].lz)
    	{
    		if(rr<=mid)
    		{
    			t[ro].rs=++tot;
    			t[t[ro].rs]=t[t[la].rs];
    			t[t[ro].rs].mx+=t[ro].lz;
    			t[t[ro].rs].lz+=t[ro].lz;
    			update(t[ro].ls,t[la].ls,l,mid,ll,rr,v,t[ro].lz);
    		}
    		else if(ll>mid)
    		{
    			t[ro].ls=++tot;
    			t[t[ro].ls]=t[t[la].ls];
    			t[t[ro].ls].mx+=t[ro].lz;
    			t[t[ro].ls].lz+=t[ro].lz;
    			update(t[ro].rs,t[la].rs,mid+1,r,ll,rr,v,t[ro].lz);
    		}
    		else
    		{
    			update(t[ro].ls,t[la].ls,l,mid,ll,mid,v,t[ro].lz);
    			update(t[ro].rs,t[la].rs,mid+1,r,mid+1,rr,v,t[ro].lz);
    		}
    		t[ro].lz=0;
    	}
    	else
    	{
    		if(rr<=mid)
    			update(t[ro].ls,t[la].ls,l,mid,ll,rr,v,0);
    		else if(ll>mid)
    			update(t[ro].rs,t[la].rs,mid+1,r,ll,rr,v,0);
    		else
    		{
    			update(t[ro].ls,t[la].ls,l,mid,ll,mid,v,0);
    			update(t[ro].rs,t[la].rs,mid+1,r,mid+1,rr,v,0);
    		}
    	}
    	ud(ro);
    }
    pair<long long,int> ques(int ro,int l,int r,int ll,int rr)
    {//cerr<<l<<" "<<r<<"   "<<ll<<" "<<rr<<endl;
    	if(l==ll&&r==rr)
    		return make_pair(t[ro].mx,t[ro].p);
    	if(t[ro].lz)
    	{
    		t[tot+1]=t[t[ro].ls];
    		t[tot+1].mx+=t[ro].lz;
    		t[tot+1].lz+=t[ro].lz;
    		t[ro].ls=tot+1;
    		t[tot+2]=t[t[ro].rs];
    		t[tot+2].mx+=t[ro].lz;
    		t[tot+2].lz+=t[ro].lz;
    		t[ro].rs=tot+2;
    		tot+=2;
    		t[ro].lz=0;
    	}
    	int mid=(l+r)>>1;
    	if(rr<=mid)
    		return ques(t[ro].ls,l,mid,ll,rr);
    	else if(ll>mid)
    		return ques(t[ro].rs,mid+1,r,ll,rr);
    	else
    	{
    		pair<long long,int>a=ques(t[ro].ls,l,mid,ll,mid),b=ques(t[ro].rs,mid+1,r,mid+1,rr);
    		return (a.first>b.first)?a:b;
    	}
    }
    int main()
    {
    	n=read(),m=read();
    	for(int i=1;i<=n;i++)
    		a[i]=g[i]=read();
    	sort(g+1,g+1+n);
    	for(int i=1;i<=n;i++)
    		if(i==1||g[i]!=g[i-1])
    			mp[g[i]]=++has,rl[has]=g[i];
    	build(rt[0],1,n);
    	for(int i=1;i<=n;i++)
    	{
    		update(rt[i],rt[i-1],1,n,i,i,1e15,0);
    		update(rt[i],rt[i],1,n,la[mp[a[i]]]+1,i,a[i],0);
    		la[mp[a[i]]]=i;//cerr<<"OK"<<endl;
    	}
    	for(int i=1;i<=n;i++)
    		q.push(qwe(i,1,i,t[rt[i]].p,t[rt[i]].mx));
    	while(m--)
    	{
    		qwe u=q.top();
    		q.pop();
    		ans=u.v;//cerr<<ans<<endl;
    		if(u.l<=u.p-1)
    		{
    			pair<long long,int>nw=ques(rt[u.d],1,n,u.l,u.p-1);
    			q.push(qwe(u.d,u.l,u.p-1,nw.second,nw.first));
    		}
    		if(u.p+1<=u.r)
    		{
    			pair<long long,int>nw=ques(rt[u.d],1,n,u.p+1,u.r);
    			q.push(qwe(u.d,u.p+1,u.r,nw.second,nw.first));
    		}
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    开机画面自己定制方法
    【转】ipc$入侵详解之终极解惑篇
    【转】动态嵌入式dll木马清除方法
    ZT:让手机使用更顺畅 PPC系统注册表修改大全(4)
    Ubuntu下用Opera不能用中文输入的解决
    Ubuntu 8 下使用vmware server 1.0.8的几个要领
    MSSQL数据库自动同步
    在Ubuntu上安装PCMCIA接口CDMA上网卡的调试笔记(ZT)
    %0 的作用
    oracle自动imp脚本
  • 原文地址:https://www.cnblogs.com/lokiii/p/10659467.html
Copyright © 2011-2022 走看看