• [NOI2019]序列


    神奇贪心

    考虑进行K次操作,每次选择一个a中的点和b中的点。

    首先,任何时刻,如果a与b中未成对的点对数量小于K-L,我们都可以选择a中最大的点和b中最大的点。

    否则,我们选择一下三种策略中收益最高的那个(如果相同则随便选)

    1.找到一个i,满足ai与bi均未被选择,选择ai与bi

    2.找到一个i,满足ai未被选择,bi已经被选择,选择ai与任意一个b

    3.找到一个i,满足bi未被选择,ai已经被选择,选择bi与任意一个a

    正确性懒得写了,大概就是如果未成对的点没选满,你早晚都要选,还不如就现在选了。

    否则的话你一定得从这三个方案中选一个,用反证法证明这么选一定不会更差就行了。

    #include<bits/stdc++.h>
    #define file(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);
    #define P 998244353
    #define mid (l+r>>1)
    #define N 1100000
    #define lb(x) (x&(-x))
    #define inf 999999999
    #define M 1658561
    #define ll long long
    #define cl(x) while(!x.empty()) x.pop();
    #define mem(x) memset(x,0,sizeof(x));
    using namespace std;
    int n,m,mx,x,y,d1,d2,d3,v1,v2,v3,a[N],b[N],va[N],vb[N],use,T,K,L;
    ll res;
    struct cp1{ bool operator() (int x,int y){return a[x]<a[y];}};
    struct cp2{ bool operator() (int x,int y){return b[x]<b[y];}};
    struct cp3{ bool operator() (int x,int y){return a[x]+b[x]<a[y]+b[y];}};
    priority_queue<int ,vector<int>,cp1>q1,q4;
    priority_queue<int ,vector<int>,cp2>q2,q5;
    priority_queue<int ,vector<int>,cp3>q3;
    int main(){
    	//file("s");
    	scanf("%d",&T);
    	while(T--){
    		res=use=0;
    		cl(q1);cl(q2);cl(q3);cl(q4);cl(q5);
    		scanf("%d%d%d",&n,&K,&L);
    		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    		for(int i=1;i<=n;i++) scanf("%d",&b[i]);
    		for(int i=1;i<=n;i++) q1.push(i),q2.push(i);
    		for(int i=1;i<=K-L;i++){
    			x=q1.top(),y=q2.top();
    			res+=a[x]+b[y],va[x]=1,vb[y]=1,q1.pop(),q2.pop();
    		}
    		for(int i=1;i<=n;i++){
    			if(va[i]&&vb[i])use++;
    			else if(va[i])q5.push(i);
    			else if(vb[i])q4.push(i);
    			else q3.push(i);
    		}
    		while(L--){
    			while(!q1.empty()&&va[q1.top()])q1.pop();
    			while(!q2.empty()&&vb[q2.top()])q2.pop();
    			while(!q3.empty()&&(va[q3.top()]||vb[q3.top()])) q3.pop();
    			while(!q4.empty()&&(va[q4.top()])) q4.pop();
    			while(!q5.empty()&&(vb[q5.top()])) q5.pop();
    			x=q1.top(),y=q2.top();
    			if(use){
    				res+=a[x]+b[y];va[x]=vb[y]=1;
    				if(!vb[x]) q5.push(x);
    				if(!va[y]) q4.push(y);
    				use+=vb[x]+va[y]-(x==y)-1;
    			}else{
    				d1=q4.empty()?0:q4.top(),d2=q5.empty()?0:q5.top(),d3=q3.empty()?0:q3.top();
    				v1=a[d1]+b[y],v2=b[d2]+a[x],v3=a[d3]+b[d3],mx=max(v1,max(v2,v3));
    				if(v1==mx) res+=a[d1]+b[y],va[d1]=vb[y]=1,va[y]? use++,void():q4.push(y);
    				else if(v2==mx) res+=b[d2]+a[x],vb[d2]=va[x]=1,vb[x]? use++,void():q5.push(x);
    				else if(v3==mx) res+=a[d3]+b[d3],va[d3]=vb[d3]=1;
    			}
    		}
    		printf("%lld
    ",res);
    		for(int i=1;i<=n;i++) va[i]=vb[i]=0;
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    什么叫工作到位?
    SQL中PIVOT 使用
    SQL中ROW_NUMBER() 使用
    Fiddler 抓包工具总结
    设计模式之单例模式
    数据库脏读、不可重复读、幻读
    SQL查询优化《四》:临时表和表变量的使用
    SQL查询优化《三》:少做重复的工作
    SQL查询优化《二》:只返回需要的数据
    SQL查询优化《一》:SQL语句执行顺序
  • 原文地址:https://www.cnblogs.com/blogoflyn/p/13252004.html
Copyright © 2020-2023  润新知