zoukankan      html  css  js  c++  java
  • 「JOI 2019 Final」 硬币收藏

    题目链接

    戳我

    (Solution)

    先将所有棋子移动到最近的目标点上

    我们设两个变量(ans1,ans2)表示到目前为止这个点上可以移动棋子的数目,然后(f[i][j])表示((i,j))上有多少个棋子,(ans)为答案

    如果为正表示从左边移到右边

    如果为负表示从右边移到左边

    我们考虑怎么维护这个东西

    我们考虑一下两种大情况:

    1. 这个位置上原本有值
      那么我们只要将(ans+(f[i][j]-1))即可

    2. 这个位置本来没有值
      我们考虑三种情况,我们以一行为例,其余的一行同理

      • (ans1)大于0,那么我们只需要将(ans1--)
      • (ans1<0)&&(ans2>0) 我们将(ans2--,ans+1)表示从下面移上来(但是对于第一行的时候要注意一个事,下面会讲)
      • 其余情况 (ans1--),表示从右边要借一个过来。

      上面留了一个坑,对于第一行的时候后,在下面一行往上移的时候我们还要判断下面一行的情况。如果下面一行(ans2==1,f[i][2]==0)那么就不能移,因为要留着自己用

    然后处理完之后会得到这一行的(ans1)(ans2)于是我们在判断一下(ans1)(ans2)是否为一正一负.

    如果是则把绝对值小的那个移到另一行去,答案加上这个绝对值。

    每次弄完之后,答案加上(abs(ans1)+abs(ans))表示往后面移这些硬币

    (Code)

    #include<bits/stdc++.h>
    #define int long long
    #define rg register
    #define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
    using namespace std;
    const int N=1e6+10;
    int read(){
        int x=0,f=1;char c=getchar();
        while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
        return f*x;
    }
    int X[N],Y[N],n,ans,flag1,flag2,ans1,ans2;
    int f[N][3];
    void solve(int x,int y){
    	int nowx=x,nowy=y;
    	if(x<=n&&x>=1&&y<=2&&y>=1) {f[x][y]++;return ;}
    	if(x>n) x=n;
    	if(x<1) x=1;
    	if(y>2) y=2;
    	if(y<1) y=1;
    	f[x][y]++,ans+=abs(nowx-x)+abs(nowy-y);	
    }
    main(){
    	n=read();
    	for(int i=1;i<=2*n;i++)
    		X[i]=read(),Y[i]=read(),solve(X[i],Y[i]);
    	for(int i=1;i<=n;i++){
    		if(f[i][1]>1) ans1+=f[i][1]-1;
    		if(f[i][2]>1) ans2+=f[i][2]-1;
    		if(f[i][1]==0){
    			if(ans1>0) ans1--;
    			else if(ans2>0&&(ans2>1||(ans2==1&&f[i][2]))) ans2--,ans+=1;
    			else ans1--;
    		}
    		if(f[i][2]==0){
    			if(ans2>0) ans2--;
    			else if(ans1>0) ans1--,ans+=1;
    			else ans2--;
    		}
    		if(ans1<0&&ans2>0) {
    			if(abs(ans1)<abs(ans2))
    				ans2=ans2+ans1,ans+=abs(ans1),ans1=0;
    			else ans1=ans2+ans1,ans+=abs(ans2),ans2=0;
    		}
    		if(ans2<0&&ans1>0) {
    			if(abs(ans1)<abs(ans2))
    				ans2=ans2+ans1,ans+=abs(ans1),ans1=0;
    			else ans1=ans2+ans1,ans+=abs(ans2),ans2=0;
    		}
    		ans+=abs(ans1)+abs(ans2);
    	}
    	cout<<ans;
        return 0;
    }
    
  • 相关阅读:
    hdu1915
    2014年9月28日 18:35:01
    洛谷—— P1122 最大子树和
    洛谷——P1103 书本整理
    洛谷—— P2049 魔术棋子
    UVA_1575
    洛谷—— P2424 约数和
    中文乱码问题
    JSP标签
    include指令
  • 原文地址:https://www.cnblogs.com/hbxblog/p/11743395.html
Copyright © 2011-2022 走看看