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;
}