T1-Fraction
给定n 求最大的分数a/b,使得a+b=n
解法
暴力枚举即可
ac代码
#include<bits/stdc++.h>
using namespace std;
int n;
int check(int a,int b)
{
for(int i=2;i<=a;i++)
if(a%i==0&&b%i==0)
return 0;
return 1;
}
int main()
{
scanf("%d",&n);
for(int i=(n-1)/2;i>=1;i--)
{
int j=n-i;
if(check(i,j)){printf("%d %d\n",i,j);break;}
}
return 0;
}
T2-Maxim Buys an Apartment
Maxim想在大都会的莱恩大道上买一座新的公寓。这幢楼房共有 n 座公寓,从 1 到 n 编号排列在一个数列中。两座相邻公寓的编号相差为 1。有一些公寓已经被售出了,另外的一些是待售的。
Maxim时常拜访他的邻居,因此如果有一座待售公寓,其相邻公寓中至少有一座是已售出的,那么这座公寓很适合Maxim。Maxim已经知道了有 k 座公寓已被售出,但是他还不知道这些已售出公寓的编号是多少。
计算出适合Maxim的公寓数可能的最小值及最大值。
解法
第一小问,不是0就是1,判断一下就可以了
第二小问,如果3k>n,那就是n-k,不然就是2k
ac代码
#include<bits/stdc++.h>
using namespace std;
int n,m,k,ans1,ans2;
int main()
{
scanf("%d%d",&n,&k);
if(k&&k!=n)ans1=1;
else ans1=0;
m=n/3;
if(m>=k)ans2=k*2;
else ans2=n-k;
printf("%d %d\n",ans1,ans2);
return 0;
}
T3-Planning
Helen在大都会机场工作,她的任务是安排每天的航班起飞时刻。今天一共有n架飞机将要起飞,第i架飞机将在第i分钟起飞。
大都会机场是大都会最重要的交通枢纽,因此想要原封不动地按照起飞时刻表的时刻起飞是很困难的。今天的情况也是如此:由于技术原因,在今天一开始的k分钟内飞机不允许起飞,因此必须创建一个新的起飞时刻表。
所有的航班必须在第(k+1)分钟到第(k+n)分钟内(包括两端)起飞,而且每分钟仅能有一架飞机起飞。然而,航班起飞的先后顺序可以与最初的时刻表排好的顺序不同,重排的时刻表只有一个限制:飞机不能比它在初始时刻表中起飞的时刻还要早的时刻起飞(即:第i架飞机必须在第i分钟后或第i分钟时起飞)。
Helen知道第i架飞机起飞时刻每延误一分钟机场所需支付的额外花费ci是多少。帮助她找到额外花费最小的方案。
解法
显然的贪心,额外花费高的要安排在前面,所以弄一个堆,每次压进去一个再取出来一个,计算一下答案就行了
ac代码
#include<bits/stdc++.h>
using namespace std;
struct node{int v,num;bool operator<(const node&x)const{return v<x.v;}};
priority_queue<node>q;
int n,k,x,res[300010];
long long ans;
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&x),q.push({x,i});
if(i>k)ans+=1ll*(i-q.top().num)*q.top().v,res[q.top().num]=i,q.pop();
}
for(int i=n+1;i<=n+k;i++)ans+=1ll*(i-q.top().num)*q.top().v,res[q.top().num]=i,q.pop();
printf("%lld\n",ans);
for(int i=1;i<=n;i++)printf("%d ",res[i]);
return 0;
}
T4-Jury Meeting
现在有(n+1)个城市,其中第1~n个城市每个城市有一个人,第0个城市是人们需要聚集的地方。还有m条航班,每条航班从0到其他城市或从其他城市到0,当天即可抵达,现在需要选定一个时间段,长度为k天,使得这一个时间段里人们都在0城市工作(航班抵达和离开0城市的那一天不能进行工作),问把n个人送到0城市,工作完成后再送回去的最小花费。
解法
预处理出a数组和b数组,其中a[i]表示i时间所有人到0号城市的最小消费,b[i]表示i时间所有人都回到自己所在城市的最小消费,处理这两个数组需要遍历所有时间与所有的边,所以复杂度是O(t+m)的,非常优了
ac代码
#include<bits/stdc++.h>
using namespace std;
struct node{int to,next,w;}ea[100010],eb[100010];
int n,m,k,t,x,y,z,st,ed,cnta,cntb,heada[1000010],headb[1000010],disa[100010],disb[100010];
long long ans=-1,a[1000010],b[1000010];
void adda(){ea[++cnta]={x,heada[t],z},heada[t]=cnta;}
void addb(){eb[++cntb]={y,headb[t],z},headb[t]=cntb;}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&t,&x,&y,&z);
if(!x)addb();else adda();
//分为x去0的边和0去y的边,分开储存
}
cnta=cntb=0;
for(int i=1;i<=1000000;i++)
{
a[i]=a[i-1];
for(int j=heada[i];j;j=ea[j].next)
{
t=ea[j].to;
if(!disa[t])cnta++,disa[t]=ea[j].w,a[i]+=disa[t];
else if(disa[t]>ea[j].w)a[i]+=ea[j].w-disa[t],disa[t]=ea[j].w;
}
//计算当前a[i]
if(!st&&cnta==n)st=i;
//如果都能到达0号点,就从此刻开始
}
for(int i=1000000;i>=1;i--)
{
b[i]=b[i+1];
for(int j=headb[i];j;j=eb[j].next)
{
t=eb[j].to;
if(!disb[t])cntb++,disb[t]=eb[j].w,b[i]+=disb[t];
else if(disb[t]>eb[j].w)b[i]+=eb[j].w-disb[t],disb[t]=eb[j].w;
}
//倒序计算当前b[i]
if(!ed&&cntb==n)ed=i;
//如果都能回到原来的城市,就最多遍历到此刻
}
if(st==0||ed==0){puts("-1");return 0;}
//如果不能都到0号点或不能都回到原来的城市,无解
for(int i=1;i<=1000000;i++)
{
if(i+k+1>ed)break;
if(i<st)continue;
if(ans==-1)ans=a[i]+b[i+k+1];
else ans=min(ans,a[i]+b[i+k+1]);
}
//枚举计算答案
printf("%lld\n",ans);
return 0;
}