주제 링크
\(해결책\)
먼저 가장 가까운 목표 지점에 모든 조각을 이동
우리는 두 변수의 설정 \ (ans1가 ans2 \)의 부분의 개수가이 시점에서, 지금까지 이동 될 수 있음을 표시하고 \ (F는 [I]는 [j는 ] \) 대표 \ (I, J의 \) 상의 부분의 개수를 , ANS는 답변입니다
당신이 왼쪽에서 오른쪽으로 이동하면 긍정적 인 표현이다
당신이 오른쪽에서 왼쪽으로 이동하면 부정적인 표현이다
우리는이 일을 유지하는 방법을 고려해야
우리는 두 개의 큰 경우를 생각 :
- 위치는 원래 값을 가지고
너무 오랫동안 우리 ANS + (F [I]와 같은 J] -1) 을 - 이 위치 값이없는 것이
우리 세 가지 사례를 고려해을, 우리는 라인의 예를 들어, 같은 방법으로 나머지 한 줄이- ans1 0보다 큰 경우, 우리는 단지 ans1-- 필요
- ans1 <0 && ans2> 우리가 ans2합니다 0 - ANS + 1은 아래에서 변화를 나타낸다 (하지만 처음으로 사물의 행에주의를 들면, 다음과 같은 말 것)
- 나머지 경우는 ans1--, 다가오는에서 빌릴 수있는 권리를 나타냅니다.
이어서이 광고 후 처리 될 (\ 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;
}