"JOI 2019 파이널"동전 수집

주제 링크

나는 찌를

\(해결책\)

먼저 가장 가까운 목표 지점에 모든 조각을 이동

우리는 두 변수의 설정 \ (ans1가 ans2 \)의 부분의 개수가이 시점에서, 지금까지 이동 될 수 있음을 표시하고 \ (F는 [I]는 [j는 ] \) 대표 \ (I, J의 \) 상의 부분의 개수를 , ANS는 답변입니다

당신이 왼쪽에서 오른쪽으로 이동하면 긍정적 인 표현이다

당신이 오른쪽에서 왼쪽으로 이동하면 부정적인 표현이다

우리는이 일을 유지하는 방법을 고려해야

우리는 두 개의 큰 경우를 생각 :

  1. 위치는 원래 값을 가지고
    너무 오랫동안 우리 ANS + (F [I]와 같은 J] -1)
  2. 이 위치 값이없는 것이
    우리 세 가지 사례를 고려해을, 우리는 라인의 예를 들어, 같은 방법으로 나머지 한 줄이
    • ans1 0보다 큰 경우, 우리는 단지 ans1-- 필요
    • ans1 <0 && ans2> 우리가 ans2합니다 0 - ANS + 1은 아래에서 변화를 나타낸다 (하지만 처음으로 사물의 행에주의를 들면, 다음과 같은 말 것)
    • 나머지 경우는 ans1--, 다가오는에서 빌릴 수있는 권리를 나타냅니다.
    우리가 선 아래 이동 상황을 판단해야 할 때 다음 라인업에 행 후 처음으로, 구덩이 위에있어. 만약 다음 라인 \ (F ans2 == 1 [ I] [2] == 0 \) 가 계속 사용 보낸 후는 이동할 수 없다

이어서이 광고 후 처리 될 (\ ans1 \)\ (ans2 \) 그리고, 우리가 어떤 결정 ans1 및 양 및 음의 여부 ans2.

다른 라인으로 이동 작은 절대 값, 플러스 대답의 절대 값을 넣어합니다.

각 후 즉, 수행 답 플러스 얻을 \ (ABS (ans1) + ABS (ANS)는 \) 이 동전의 뒷면에 변화를 나타냅니다

\(암호\)

#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;
}

추천

출처www.cnblogs.com/hbxblog/p/11743395.html