[bzoj1105]石头花园

首先$C/2=x_{max}+y_{max}-x_{min}-y_{min}=max(x_{max},y_{max})-min(x_{min},y_{min})+min(x_{max},y_{max})-max(x_{min},y_{min})$,容易发现前两项都是定值,那么就是要最小化后面的数字
构造:让所有数都满足$x\le y$,那么必然使得$min(x_{max},y_{max})$最小,$max(x_{min},y_{min})$最大,也就是令周长最小
然后考虑最小化重量和,根据上面的构造,我们发现必须要两者同时取到极值才能最小,也就是可以分别构造,不妨枚举最大值的位置和次大值的位置(最小值同理),一共2*2=4种状态分类讨论即可
(注意:要判定无解,因为有可能某两个不同类型(大和小)的值同时出现在一个点中,导致两种情况都不符合)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 1000005
 4 int n,mx1,mx2,mn1,mn2,ans,x[N],y[N],w[N];
 5 int calc(int mx1,int mx2,int mn1,int mn2){
 6     int ans=0;
 7     for(int i=1;i<=n;i++)
 8         if ((x[i]>mx1)||(x[i]<mn1)||(y[i]>mx2)||(y[i]<mn2)){
 9             swap(x[i],y[i]);
10             ans+=w[i];
11             if ((x[i]>mx1)||(x[i]<mn1)||(y[i]>mx2)||(y[i]<mn2)){
12                 swap(x[i],y[i]);
13                 return 2e9;
14             }
15             swap(x[i],y[i]);
16         }
17     return ans;
18 }
19 int main(){
20     scanf("%d",&n);
21     mn1=mn2=1e9;
22     for(int i=1;i<=n;i++){
23         scanf("%d%d%d",&x[i],&y[i],&w[i]);
24         mx1=max(mx1,max(x[i],y[i]));
25         mx2=max(mx2,min(x[i],y[i]));
26         mn1=min(mn1,min(x[i],y[i]));
27         mn2=min(mn2,max(x[i],y[i]));
28         ans+=w[i];
29     }
30     for(int i=0;i<2;i++){
31         for(int j=0;j<2;j++){
32             ans=min(ans,calc(mx1,mx2,mn1,mn2));
33             swap(mn1,mn2);
34         }
35         swap(mx1,mx2);
36     }
37     printf("%lld %d",2LL*(mx1+mx2-mn1-mn2),ans);
38 }
View Code
posted @ 2019-12-18 15:53  PYWBKTDA  阅读(207)  评论(0编辑  收藏  举报