zoukankan      html  css  js  c++  java
  • 使用单调队列维护决策三元组实现决策单调性优化DP的一些细节

    [BZOJ2687]交与并为例给出代码。

    #include <bits/stdc++.h>
    
    #define rin(i,a,b) for(register int i=(a);i<=(b);++i)
    #define irin(i,a,b) for(register int i=(a);i>=(b);--i)
    #define trav(i,a) for(register int i=head[a];i;i=e[i].nxt)
    #define Size(a) (int)a.size()
    #define pb push_back
    #define lowbit(x) ((x)&(-(x)))
    typedef long long LL;
    
    using std::cerr;
    using std::endl;
    
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    	return x*f;
    }
    
    const int MAXN=1000005;
    
    int n,tot;
    LL ans;
    
    struct seg{
    	int l,r;
    	inline friend bool operator < (seg x,seg y){
    		return x.l==y.l?x.r>y.r:x.l<y.l;
    	}
    }a[MAXN],b[MAXN];
    
    inline LL calc(seg x,seg y){
    	if(x.r<=y.l)return 0;
    	return 1ll*(y.r-x.l)*(x.r-y.l);
    }
    
    int bit[MAXN];
    inline void ins(int x,int y){for(register int i=x;i<=1e6;i+=lowbit(i))bit[i]=std::max(bit[i],y);}
    inline int ask(int x){int ret=0;for(register int i=x;i;i-=lowbit(i))ret=std::max(ret,bit[i]);return ret;}
    
    int hd,tl;
    
    struct Opt{
    	int j,l,r;
    }q[MAXN];
    
    int main(){
    	n=read();
    	rin(i,1,n)a[i].l=read(),a[i].r=read();
    	std::sort(a+1,a+n+1);
    	int maxr=0;
    	rin(i,1,n){
    		if(a[i].r<=maxr){
    			ans=std::max(ans,1ll*(a[i].r-a[i].l)*ask(1e6-a[i].r+1));
    			continue;
    		}
    		maxr=a[i].r;
    		b[++tot]=a[i];
    		ins(1e6-a[i].r+1,a[i].r-a[i].l);
    	}
    	n=tot;hd=tl=1;q[1]=(Opt){1,2,n};
    	rin(i,2,n){
    		int j=q[hd].j;
    		ans=std::max(ans,calc(b[j],b[i]));
    		++q[hd].l;if(q[hd].l>q[hd].r)++hd;
    		int pos=0;
    		while(1){
    			if(hd>tl){pos=i+1;break;}// 当队列为空时直接插入
    			int jt=q[tl].j,lt=q[tl].l,rt=q[tl].r;
    			if(calc(b[i],b[rt])<calc(b[jt],b[rt])){pos=rt+1;break;}// 在q[tl].r处严格劣于队尾决策时插入队尾
    			else if(calc(b[i],b[lt])>=calc(b[jt],b[lt])){--tl;continue;}// 在q[tl].l处不劣于队尾决策时删除队尾
    			else{
    				int l=lt,r=rt;
    				while(l<=r){
    					int mid=((l+r)>>1);
    					if(calc(b[i],b[mid])>=calc(b[jt],b[mid]))pos=mid,r=mid-1;// 找到队尾决策所对应区间内第一个不劣于队尾决策的位置
    					else l=mid+1;
    				}
    				q[tl].r=pos-1;// 更新队尾决策所对应区间的右端点
    				break;
    			}
    		}
    		if(pos<=n)q[++tl]=(Opt){i,pos,n};
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    单例模式
    js事件
    oracle_to_excel
    jquery_2
    jquery_1
    4.linux 复制,删除,重命名
    一个tomcat下部署多个springboot项目
    3.centos7 安装oracle
    桥接模式
    组合模式
  • 原文地址:https://www.cnblogs.com/ErkkiErkko/p/10644448.html
Copyright © 2011-2022 走看看