"JOI 2019 Final" coin collection

Topic Link

I poke

\(Solution\)

First move all the pieces to the nearest target point

We set up two variables \ (ans1, ans2 \) indicates the number of pieces can be moved so far on this point, then \ (f [i] [j ] \) represents \ (i, j \) the number of pieces on , ans is the answer

If you move from left to right is positive representation

If you move from right to left is negative representation

We consider how to maintain this thing

We think of the two big cases:

  1. The position originally had a value
    so long as we ans + (f [i] [ j] -1) to
  2. This position would have no value
    we consider three cases, we have one line, for example, the same way the rest of the line
    • ans1 greater than 0, then we only need to ans1--
    • ans1 <0 && ans2> 0 we will ans2 -, ans + 1 represents the shift up from below (but for the first time to pay attention to a row of things, the following will speak)
    • The remaining cases ans1--, represent the right to borrow from a coming.
    Stay above a pit, for the first time after row, in the following line-up when we have to judge the situation shifted below the line. If the following line \ (ans2 == 1, f [ i] [2] == 0 \) then it can not move, since they used to keep

Then will be processed after this line \ (ans1 \) and \ (ans2 \) and then we determine what ans1 and ans2 whether a positive and negative.

If you put a small absolute value that is moved to another line, plus the absolute value of the answer.

After each get that done, the answer plus \ (abs (ans1) + abs (ans) \) represents the shift to the back of these coins

\(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;
//  cout<<x<<" "<<y<<endl;
    f[x][y]++,ans+=abs(nowx-x)+abs(nowy-y);
    
}
main(){
//  file("coin");
    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;
}

Guess you like

Origin www.cnblogs.com/hbxblog/p/11743395.html