cf352div2 C D

链接: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;
}


<div id="wea_rich_text_default_font" style="font-family:微软雅黑;font-size:12;"><p><img alt="" src="/weaver/weaver.file.FileDownload?fileid=aaa9aee4717d33272bd7ea028fa03118b693919f23b18febf9f6cee1158e8f4cf027542c71c8cf98d63770ccdf3bd1750e6b92e28c43dccd4" /></p><div class="ckeditor-html5-video" data-widget="html5video" style="text-align:left"><video controls="controls" src="/weaver/weaver.file.FileDownload?fileid=aad6f413f83191673980c5ee24b412880d6b9e8703caca411faec3276fe8133f5fa7e34630ca89ace63770ccdf3bd175071362141037cfb4e&download=1" style="max-width:100%"> </video></div><table border="1" cellpadding="1" style="width:500px;"> <tbody> <tr> <td style="padding: 1px;">1</td> <td style="padding: 1px;">1</td> </tr> <tr> <td style="padding: 1px;">2</td> <td style="padding: 1px;">2</td> </tr> <tr> <td style="padding: 1px;">3</td> <td style="padding: 1px;">3<a href="http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830" target="_blank">http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830</a></td> </tr> </tbody></table><p>测试<a href="http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830" target="_blank">http://localhost:8080/wui/index.html#/main/portal/portal-1-1?menuIds=0,1&menuPathIds=0,1&_key=zq8830</a></p><p> </p><p>修改一下吧 qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq<img alt="" src="/weaver/weaver.file.FileDownload?fileid=a7617945ec5f52ec80aaa43ee8504de0a1b14d5eca4a98834494c85349762c626dec7ba8d0da277106ee600d27743f4e44f710fbddd167603" /></p></div>
06-01
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值