ACM训练_week1_2

版权声明:本文为博主原创文章,如果转走了就评论说一声就好了哈。 https://blog.csdn.net/qq_36124802/article/details/80473238

codeforces上gym的一场,三题,菜到爆炸,打到现在还出不了什么题

2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017)

K(二分+小数据枚举):

题意上由3种人,每种人有一个不同的速度值vi,每种人分别又有k个,然后有总人数/2点划艇数,每个划艇有一个常数b,每两个人需要在一个划艇上面有一个速度值V=b*(v1+v2),问如何分配划艇使得最小的那个划艇速度最大。

最小最大值问题,显然二分。数据小,显然可以枚举,后面也想过枚举,不过貌似有其他题可以出,所有就弃了,还是太菜。

当时想的是最小v的那个人必定选择最大常数的划艇V,然后去二分满足某个速度应该最起码与最小速度的那个人是哪一位,这么贪是错的,因为如果人的速度为1,50,50,100,那么显然50+50<100+1,而小的那个才应该选择大的划艇,此时因为数据小,对每个游艇枚举所有可能的人的组合,取一个最小的vi+vj作为答案就好了。

源码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const double eps=1e-9;
    const ll maxn=1e5+7;
    ll qq[maxn];
    ll t[5];
    ll k[5];
    ll cmp1(ll x,ll y){
        return x>y;
    }
    ll bb[5];
    int main(){
        ll i,j,f1,f2,f3,f4,n,m,t1,t2,t3,t4,t5,t6,t7;
        ll T;
        ll l;
        ll k1,k2,k3,k4,k5,k6;
        //freopen("in.txt","r",stdin);
        //freopen("out1.txt","w",stdout);
        cin >> t[1] >> t[2] >> t[3];
        bb[1]=t[1];
        bb[2]=t[2];
        bb[3]=t[3];
        cin >> k[1] >> k[2] >> k[3];
        n = t[1]+t[2]+t[3];
        for(i=1;i<=n/2;i++)
        cin >> qq[i];
        sort(qq+1,qq+1+n/2,cmp1);
        ll left1,right1,mid1;
        left1=1;
        right1=1e9;
        ll pos;
        ll res;
        ll max1=0;
        ll u,v;
        ll cost;
        while(right1>=left1){
        mid1=(left1+right1)/2;
        res=0;
        t[1]=bb[1];
        t[2]=bb[2];
        t[3]=bb[3];
        for(i=1;i<=n/2;i++){
       // cout << mid1 << "res = " <<res << endl;
            u=v=0;
            cost=1e9;
            for(j=1;j<=3;j++)
                for(l=j;l<=3;l++){
                    if(l!=j&&t[l]>0&&t[j]>0){
                        if(qq[i]*(k[l]+k[j])>=mid1){
                            if(k[l]+k[j]<cost){
                                u=l;v=j;
                                cost=k[l]+k[j];
                            }
                        }
                    }else if(l==j&&t[j]>=2){
                        if(qq[i]*(k[l]+k[j])>=mid1){
                        if(k[l]+k[j]<cost){
                                u=l;v=j;
                                cost=k[l]+k[j];
                            }
                    }
                }
                }
            //cout <<"i=   "<<  u <<"    " << v<< endl;
        if(cost==1e9)res=1;
        else{
        t[v]--;t[u]--;
        }
        }
        if(res==0){
            max1=max(max1,mid1);
            left1=mid1+1;
        }else{
            right1=mid1-1;
        }
        }
        cout << max1 << endl;
        return 0;
    }

G(降维+树状数组+离散化):

注意存数据中点细节问题

题意:给一场acm交题的现场,每题都AC,给num=i的队伍点交题时间,问每次有人交题以后num=1的排名是多少。

排名是由于交题+罚时两个条件判定,题目越多,名次越前,题目相同时候判时(这里可以转换为每个人刚开始有1e18的分数,每A一道题-1e9+交题时间,这样可以确保题目数量越多的人,排名越靠前,罚时多的人+比较多的时间,排名比较后面,因为只有1e5种情况,全部离散化,然后用树状数组处理一下即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps=1e-9;
const ll maxn=2e5+7;
ll qq[maxn];
ll t[5];
ll k[5];
ll cmp1(ll x,ll y){
    return x>y;
}
ll bb[5];

//把需要离散化的内容进行排序,去重,然后getid为取得这个值的下标
vector<ll>v;
ll getid(ll x){
	return lower_bound(v.begin(),v.end(),x)-v.begin()+1LL; //错1次,返回下标需要-v.begin()+1
}
vector<ll>num[maxn];
struct ttt{
    ll a,b;
};
ttt q1[maxn];
vector<ll>num2[maxn];
ll lowbits(ll x){
    return x&(-x);
}
ll NN;
ll c1[maxn];
ll sum(ll x){
    ll sum1=0;
    while(x>0){
    sum1+=c1[x];
    x-=lowbits(x);
    }
    return sum1;
}
ll add(ll x,ll y){
    while(x<=NN){
        c1[x]+=y;
        x+=lowbits(x);
    }
}
int main(){
    ll i,j,f1,f2,f3,f4,n,m,t1,t2,t3,t4,t5,t6,t7;
    ll T;
    ll k1,k2,k3,k4,k5,k6;
    freopen("in","r",stdin);
    //freopen("out1.txt","w",stdout);
    cin >> n  >> m;
    NN=1e5+3;
    ll len=1e9+7;
    ll K=1e16;
    ll ff;
    for(i=1;i<=m;i++){
    cin >> t1 >> t2;
    q1[i].a=t1;
    q1[i].b=t2;
    f1=num[t1].size();
    if(f1==0){
        ff=len-t2;
        num[t1].push_back(len-t2);
        v.push_back(K-ff);
    }else{
        ff=len-t2+num[t1][f1-1];
        num[t1].push_back(len-t2+num[t1][f1-1]);
        v.push_back(K-ff);
    }
    }
    v.push_back(v[v.size()-1]+1);
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    ll id;
    ll cost=v[v.size()-1]+1;
    for(i=1;i<=m;i++){
    t1=q1[i].a;
    t2=q1[i].b;
    f1=num2[t1].size();
    if(t1==1&&f1==0){
    ff = len-t2;
    cost = K-ff;
    num2[t1].push_back(len-t2);
    }else if(t1==1){
    ff=len-t2+num2[t1][f1-1];
    cost = K-ff;
    num2[t1].push_back(ff);
    }
    //cout << t1 <<"    " <<t2<< endl;
    //cout <<"~~ qiang " << endl;
    if(f1==0&&t1!=1){
        //cout <<"555" << endl;
        ff=len-t2;
        num2[t1].push_back(len-t2);
       // cout <<"kkk " << endl;
        id = getid(K-ff);
       // cout <<" 666" << endl;
        add(id,1);
      //  cout <<"insert1 " << id << endl;
    }else if(t1!=1){
        id=getid(K-num2[t1][f1-1]);
       // cout <<"delete " << id << endl;
        add(id,-1);
        num2[t1].push_back(len-t2+num2[t1][f1-1]);//输入的为得分
        id=getid(K-(len-t2+num2[t1][f1-1]));
       // cout <<"insert " << id << endl;
        add(id,1);
    }
    id=getid(cost);
    cout << sum(id-1)+1 << endl;
    }
    return 0;
}



猜你喜欢

转载自blog.csdn.net/qq_36124802/article/details/80473238