zoukankan      html  css  js  c++  java
  • loj 3153& floj 2453

    题意:

    题目链接
    给出一个长度为n(n<=5e5)的序列A,给出q(q<=5e5)个询问
    每个询问包含L,R
    要求在[L,R]中选择a,b,c三个数满足a<b<c且b-a<=c-b
    求在满足条件的情况下,(A_a+A_b+A_c)的最大值

    题解:

    考虑对于一组最优解(a,b,c)
    对于任意x满足a<x<b
    如果有(A_x>A_a),那么(x,b,c)显然更优,矛盾
    如果有(A_x>A_b),那么(a,x,c)显然更优,矛盾
    因此(A_x<=min(A_a,A_b))
    那么我们考虑用单调栈维护这样的(a,b)数对(个数是(O(n))的)
    然后每次都用后缀和计算(A_c)的最大值
    总复杂度(O(n^2))
    考虑如何进一步优化
    我们记(f_i)表示c=i时(A_a+A_b+A_c)的最大值
    离线下所有的询问,然后倒序扫描
    枚举到a时,处理所有的二元组(a,b)
    对于所有的i满足(i>=2b-a),修改(f_i=max(f_i,A_a+A_b+A_i))
    那么对于区间[L,R]答案就是(max_{i=L}^R f_i)
    线段树维护一下就好了

    code:

    #include<bits/stdc++.h>
    using namespace std;
    const int N=5e5+5;
    typedef pair<int,int> pii;
    typedef long long ll;
    #define fi first
    #define se second
    int n,sta[N],top,m;
    ll ans[N],mx[N<<2],a[N],tag[N<<2],tmp[N<<2];
    vector<int>pos[N];
    vector<pii>q[N];
    inline int read()
    {
    	int s=0,w=1; char ch=getchar();
    	for(;!isdigit(ch);ch=getchar())if(ch=='-')w=-1;
    	for(;isdigit(ch);ch=getchar())s=(s<<1)+(s<<3)+(ch^48);
    	return s*w;
    }
    #define lc (rt<<1)
    #define rc (rt<<1|1)
    inline void mt(int rt,ll u)
    {
    	mx[rt]=max(mx[rt],u+tmp[rt]);
    	tag[rt]=max(tag[rt],u);
    }
    inline void down(int rt)
    {
    	if(!tag[rt])return;
    	mt(lc,tag[rt]),mt(rc,tag[rt]);
    	tag[rt]=0;
    }
    inline void up(int rt){mx[rt]=max(mx[lc],mx[rc]);}
    void build(int rt,int l,int r)
    {
    	if(l==r){tmp[rt]=a[l];return;}
    	int mid=l+r>>1;
    	build(lc,l,mid);build(rc,mid+1,r);
    	tmp[rt]=max(tmp[lc],tmp[rc]);
    }
    void update(int rt,int l,int r,ll u,int bl=1,int br=n)
    {
    	if(l<=bl&&br<=r){mt(rt,u);return;}
    	down(rt);
    	int mid=bl+br>>1;
    	if(l<=mid)update(lc,l,r,u,bl,mid);
    	if(mid<r)update(rc,l,r,u,mid+1,br);
    	up(rt);
    }
    ll query(int rt,int l,int r,int bl=1,int br=n)
    {
    	if(l<=bl&&br<=r)return mx[rt];
    	down(rt);
    	int mid=bl+br>>1;ll res=0;
    	if(l<=mid)res=max(res,query(lc,l,r,bl,mid));
    	if(mid<r)res=max(res,query(rc,l,r,mid+1,br));
    	up(rt);
    	return res;
    }
    #undef lc
    #undef rc
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;++i)a[i]=1ll*read();
    	for(int i=1;i<=n;++i)
    	{
    		while(top&&a[sta[top]]<a[i])pos[sta[top--]].push_back(i);
    		if(top)pos[sta[top]].push_back(i);sta[++top]=i;
    	}
    	build(1,1,n);
    	m=read();
    	for(int i=1;i<=m;++i)
    	{
    		int l=read(),r=read();
    		q[l].push_back(make_pair(r,i));
    	}
    	for(int i=n;i>=1;--i)
    	{
    		for(vector<int>::iterator it=pos[i].begin();it!=pos[i].end();it++)
    			if(*it+*it-i<=n)update(1,*it+*it-i,n,a[i]+a[*it]);
    		for(vector<pii>::iterator it=q[i].begin();it!=q[i].end();it++)
    			ans[(*it).se]=query(1,i,(*it).fi);
                    //脑抽了,vector直接像数组那样遍历更方便
    	}
    	for(int i=1;i<=m;++i)printf("%lld
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    适配器
    适配器
    哈希容器
    迭代器
    redis介绍
    9内核同步介绍
    Redis基础数据结构
    springCloud-Eureka源码分析
    zookeeper伪分布式集群环境搭建
    消息队列核心-如何保证消息不丢失
  • 原文地址:https://www.cnblogs.com/zmyzmy/p/13681176.html
Copyright © 2011-2022 走看看