• P6117[JOI 2019 Final]コイン集め【贪心】


    正题

    题目链接:https://www.luogu.com.cn/problem/P6117


    题目大意

    平面上有\(2n\)的硬币,要给每个硬币匹配一个\(x\in[1,n],y\in[1,2]\)的位置(不能重复)。

    使得所有硬币和它们匹配位置的曼哈顿距离之和最小。

    \(1\leq n\leq 10^5,-10^9\leq X_i,Y_i\leq 10^9\)


    解题思路

    先把每个硬币先移进\(x\in[1,n],y\in[1,2]\)这个范围内,然后考虑贪心去把每个硬币匹配。

    我们在同一个\(x\)的硬币如果上下直接能够补充缺口那么肯定优先上下补充。

    不然就从左到右考虑,那么最左边的肯定往右移动多余/请求空缺,记\(f_{i,j}\)表示位置\((i,j)\)现在的需求情况即可。

    时间复杂度:\(O(n)\)


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const ll N=1e5+10;
    ll n,g[N][2],ans;
    signed main()
    {
    	scanf("%lld",&n);
    	for(ll i=1,x,y;i<=2*n;i++){
    		scanf("%lld%lld",&x,&y);
    		if(y>=2)ans+=y-2,y=2;
    		else ans+=1-y,y=1;
    		if(x>n)ans+=x-n,x=n;
    		else if(x<1)ans+=1-x,x=1;
    		g[x][y-1]++;
    	}
    	for(ll i=1;i<=n;i++){
    		g[i][0]--;g[i][1]--;
    		if(g[i][0]*g[i][1]<0){
    			if(g[i][0]<0){
    				ll p=min(-g[i][0],g[i][1]);
    				g[i][0]+=p;g[i][1]-=p;
    				ans+=p;
    			}
    			else{
    				ll p=min(g[i][0],-g[i][1]);
    				g[i][0]-=p;g[i][1]+=p;
    				ans+=p;
    			}
    		}
    		ans+=abs(g[i][0])+abs(g[i][1]);
    		g[i+1][0]+=g[i][0];
    		g[i+1][1]+=g[i][1];
    	}
    	printf("%lld\n",ans);
    	return 0;
    }
    
  • 相关阅读:
    mac os 基本命令
    一个程序员的郁闷吐槽
    域名那些事儿
    EventEmitter事件派发器
    Array类型的操作方法
    居中与垂直居中
    Web Storage —— 登录时记住密码
    字符串字符统计
    颜色字符串转换(正则)
    将字符串转换为驼峰格式
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/16402090.html
Copyright © 2020-2023  润新知