链接:http://codeforces.com/contest/672
C:
给你两个人的位置x1,y1,x2,y2和垃圾桶在的位置x,y,和n个垃圾的位置,每次一个人只能带一个垃圾,求将所有垃圾丢到垃圾桶要走的最短距离。
分析:如果两个人都到了垃圾桶,那么以后都相当于是一个人再走。所以a或b都可以选择带一个或不带垃圾走。我们的目的就是要找到这个垃圾。
我们按选这个垃圾能少的距离排序,然后再判断多种情况。
我们直接分析3中情况:1:只有a走动。2:只有b走动。3:a,b都走动。然后取最小就行了。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 200010
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
#define eps 1e-10
int a[Mn],b[Mn];
struct node {
double dis;
int i;
node(){}
node(double dis,int i):dis(dis),i(i){}
bool operator <(const node x) const {
if(x.dis-dis<0) return 0;
return 1;
}
}pa[Mn],pb[Mn];
double getdis(double x,double y,double c,double d) {
return sqrt((x-c)*(x-c)+(y-d)*(y-d));
}
double dis[Mn];
int main() {
int x1,y1,x2,y2,t1,t2;
int n;
scanf("%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&t1,&t2);
double ans=0.0;
double disa=getdis(x1,y1,t1,t2);
double disb=getdis(x2,y2,t1,t2);
scanf("%d",&n);
for(int i=0;i<n;i++) {
scanf("%d%d",&a[i],&b[i]);
dis[i]=getdis(a[i],b[i],t1,t2);
pa[i]=node(dis[i]-getdis(x1,y1,a[i],b[i]),i);
pb[i]=node(dis[i]-getdis(x2,y2,a[i],b[i]),i);
ans+=dis[i]*2;
}
sort(pa,pa+n);
sort(pb,pb+n);
int pos=n-1;
double ans1=min(ans-pa[pos].dis,ans+disa);
double ans2=min(ans-pb[pos].dis,ans+disb);
double ans3;
if(pb[pos].i==pa[pos].i) {
if(pb[pos].dis+pa[pos-1].dis>pa[pos].dis+pb[pos-1].dis) {
ans3=ans-pb[pos].dis-pa[pos-1].dis;
} else {
ans3=ans-pa[pos].dis-pb[pos-1].dis;
}
} else {
ans3=ans-pa[pos].dis-pb[pos].dis;
}
printf("%.10f\n",min(ans1,min(ans2,ans3)));
return 0;
}
D:
给你一个序列,k次操作,每次操作将一个数的减一,另一个数加一,问在有限操作下求最大值最小值的差的最小。
分析:我们可以二分出上届和下届,然后判断一下输出就行。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 500010
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int a[Mn],n,k;
bool xia(int x) {
ll lsum=0;
for(int i=0;i<n;i++) {
if(a[i]<x) lsum+=x-a[i];
}
if(lsum>k) return false;
return true;
}
bool da(int x) {
ll sssum=0;
for(int i=0;i<n;i++) {
if(a[i]>x) sssum+=(a[i]-x);
}
if(sssum>k) return false;
return true;
}
int main() {
scanf("%d%d",&n,&k);
ll sum=0;
for(int i=0;i<n;i++) {
scanf("%d",&a[i]);
sum+=a[i];
}
int l=1,r=1e9;
int ans1;
while(l<r) {
int mid=(l+r+1)>>1;
if(xia(mid)) {
l=mid;
} else r=mid-1;
}
ans1=l;
l=1,r=1e9;
int ans2;
while(l<r) {
int mid=(l+r)>>1;
if(da(mid)) {
r=mid;
} else l=mid+1;
}
ans2=r;
//cout<<ans1<<" "<<ans2<<endl;
if(ans2<=ans1) cout<<(sum%(ll)n?1:0)<<endl;
else cout<<ans2-ans1<<endl;
return 0;
}