20170702练习赛比赛总结

A

思路&反思
  • 发现人只有在接受到声音后才会进入咆哮,所以不可以通过二分一个时间后把每个人独立开算
  • 仔细思考发现对于一个人一个人分析过来的他们只有一个最优的情况可以使时间最短,于是可以直接模拟
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M=1e5+5;
bool mark[M];
int n,tot;
D k,ans,A[M],B[M],use;
int main(){
    scanf("%lf%d",&k,&n);
    for(int i=1;i<=n;i++)scanf("%lf",A+i);
    sort(A+1,A+1+n);A[1]+=k;
    /*我们用A[i]表示一个人可以受影响的最远距离*/
    for(int i=1;i<n;i++){
        A[i+1]-=use;    
        if(A[i]>=A[i+1]){
            /*有可能一个人一直跑也跑不出前一个人可以影响的最远距离*/ 
            if(A[i+1]+use<=A[i])A[i+1]+=use;
            if(A[i+1]+use<=A[i])A[i+1]=A[i+1]+use+k;
            else A[i+1]=A[i]+k;
            continue;
        }else{
            D d=(A[i+1]-A[i])/2;
            use+=d;
            A[i+1]=A[i+1]-d+k;
        }
    }
    printf("%.4f",use);
    return 0;
}
小结
  • 在情景感很强的题目中我们一定要仔细分析好题目的限制条件和各种情况后再来解答
  • 同时我们也不要拘泥于一定要利用高端的算发来解决问题,可以寻找最优答案形成的过程来贪心

B

  • 我们发现顺序是对问题的解没有影响的,于是问题就转化成区间的覆盖问题了
  • 如果没有 K 这个限制条件,问题就很简单了。所以开始考虑K
/*
    我们定义dp[i] 表示覆盖[1,i]区间的最小花费 
    于是我们有以下的转移方程 
    1.对于[1,i]的中的l且(A[i]-A[l]>k) 
    dp[i]=dp[l-1]+(A[i]-A[l]);
    2.对于(A[i]-A[l-1]<=k)时更新 
    dp[i]=dp[l-1]+k;
*/
#include<bits/stdc++.h>
#define For(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int M=3e5+5;
int n,m,k,A[M],dp[M],l=1,mi=1e9;
int main(){
    scanf("%d %d %d",&m,&k,&n);
    For(i,1,n)scanf("%d",&A[i]);
    sort(A+1,A+1+n);dp[1]=k;
    For(i,2,n){
        while(A[i]>=A[l]+k)mi=min(dp[l-1]-A[l]+1,mi),l++;
        dp[i]=min(A[i]+mi,dp[l-1]+k);
    }printf("%d",dp[n]);
    return 0;
}

C

  • 找规律之后最短路
#include<bits/stdc++.h>
#define For(i,a,b) for(int i=a;i<=b;++i)
#define pb(a) push_back(a)
#define sz(a) a.size()
using namespace std;
typedef long long ll;
const int M=6e5+5;
const ll INF=(ll)1e18;
int h[M],nxt[M],tot,t[M],num;
ll c[M],D[M],A[M][2],dis[M],n,m;
bool mark[M];
void Add(int x,int y,ll C){
    c[++tot]=C,t[tot]=y,nxt[tot]=h[x],h[x]=tot;
    c[++tot]=C,t[tot]=x,nxt[tot]=h[y],h[y]=tot;
}
ll to(ll x){
    ll k=sqrt(x);
    ll a=k*k,b=k*k-(4*k-4)+1;
    if(k*k==x)return b; 
    if(x<a+(k+1))return b-a-2+x;
    return b-a-4+x; 
}
struct P{
    int t;ll c;
    bool operator<(const P&A)const {return c>A.c;}
};
ll SP(int S,int T){
    priority_queue<P>Q;
    for(int i=1;i<=num;i++)dis[i]=INF;
    dis[S]=0;
    Q.push((P){S,0});
    while(!Q.empty()){
        P to=Q.top();Q.pop();
        int x=to.t;
        if(x==T)return dis[x];
        for(int i=h[x];i;i=nxt[i]){
            int y=t[i];ll co=c[i];
            if(dis[y]>dis[x]+co){
                dis[y]=dis[x]+co;
                Q.push((P){y,dis[y]});
            }
        }
    }
}
int main(){
    cin>>n>>m;
    D[++num]=1;
    for(int i=1;i<=m;i++){
        scanf("%lld",&A[i][0]);
        A[i][1]=to(A[i][0]);
        D[++num]=A[i][0];
        D[++num]=A[i][1];
    }D[++num]=n;
    sort(D+1,D+num+1);
    num=unique(D+1,D+num+1)-D-1;
    for(int i=1;i<=m;i++){
        A[i][0]=lower_bound(D+1,D+1+num,A[i][0])-D;
        A[i][1]=lower_bound(D+1,D+1+num,A[i][1])-D;
        Add(A[i][0],A[i][1],1);
    }
    for(int i=1;i<num;i++)Add(i,i+1,D[i+1]-D[i]);
    int S=lower_bound(D+1,D+1+num,1)-D;
    int T=lower_bound(D+1,D+1+num,n)-D;
    printf("%lld\n",SP(S,T));
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值