gym102136C. Kingdom Partition /Aizu - 2786G - Share the Ruins Preservation

https://codeforces.com/gym/102136/problem/C

https://vjudge.net/contest/145955#problem/G

这两题一样啊。。。维护一个前缀凸包和后缀凸包就行了

#include<bits/stdc++.h>
using namespace std;
 
const int N=2e5+10;
 
struct P{
     long long x,y;
     long long operator *(const P &a)const{
          return x*a.y-y*a.x;
     }
     P operator -(const P &a)const{
         return P{x-a.x,y-a.y};
     }
}A[N],q[N*5];
 
 
long long pre[N],suf[N],n;
int cmp(P a,P b){
    if(a.x==b.x) return a.y<b.y;
    return a.x<b.x;
}
void solve(int kind){
     int i,l=3e5,r=l;
     q[l]=q[r]=A[1];
     long long res=0;
     for(i=2;i<=n;i++){
        while(r-l+1>=3&&(q[l]-q[l+1])*(A[i]-q[l])<0){
            res+=abs((q[l]-q[l+1])*(A[i]-q[l]));
            l++;
        }
        while(r-l+1>=3&&(q[r]-q[r-1])*(A[i]-q[r])>0){
            res+=abs((q[r]-q[r-1])*(A[i]-q[r]));
            r--;
        }
        q[--l]=A[i];
        q[++r]=A[i];
        if(kind==1) pre[i]=res;
        else suf[i]=res;
     }
}
 
 
int main(){
    long long i,s;
    scanf("%lld",&n);
    for(i=1;i<=n;i++) scanf("%lld%lld",&A[i].x,&A[i].y);
 
 
    sort(A+1,A+1+n,cmp);
    solve(1);
 
    reverse(A+1,A+1+n);
    for(i=1;i<=n;i++) A[i].x*=-1;
 
    solve(0);
    //s*=2;
 	
    //long long res=pre[n],ans=res;
    long long ans=pre[n];
	for(i=1;i<n;i++){
        if(A[i].x!=A[i+1].x){
        /*    res=abs(suf[i]-pre[n-i]);
            if(abs(res-s)<abs(ans-s)) ans=res;
            else if(abs(res-s)==abs(ans-s)&&res<ans) ans=res;
        */
        	ans=min(ans,suf[i]+pre[n-i]);	
		}
    }
    if(ans&1) ans=ans/2+1;
    else ans=ans/2;
    printf("%lld\n",ans);	
   // printf("%.6f\n",ans/2.0);
 
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/113407853