Codeforces Round #503 (by SIS, Div. 2) ABC总结

首先,我个人觉得这套题比较烂。。。除了题干长以外,题目也是有一点恶心。然后重回绿名。

A:给你n个相邻的建筑(从左到右编号1到n),每个建筑有h层,每个建筑的a层到b层中任意一层c层可以花一秒直接到隔壁建筑的c层。上下楼1层需要1秒。求q次查询(建筑a,层a)到(建筑b,层b)的最短时间。唯一的坑点就是同一层楼要特判。(然而我还是WA了一发)

B:老师要问一个同学a,这个人会说另一个b,然后老师会批评b,然后b会说同学c,老师再去批评c,依次下去,直到有一个人被批评了两次。求老师问同学1~n时,第一次被批评两次的这个人。直接爆搜就可以。。。感觉比第一题还简单。。。

C:n个选民,m个竞争者(编号1~m),你是1号竞争者。给出每个选民准备选的竞争者,和让这个选民选你的花费。求最小的花费让你胜出(胜出就是你的票数大于其他任何竞争者的票数)。刚开始准备各种模拟,然后样例都过不了。。。比赛的时候干了一个半小时没干出来。其实方向想错了。应该枚举答案而不是直接模拟过程。因为总有一个得票数i(1<=i<=n),让你胜出。然后枚举每个i,把得票数大于等于i的竞争者中选他们的选民买通给自己投票,直到他的得票数小于i,然后再看自己票数是否能够达到i,不够补一下。最后能达到就取一下最小费用。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=3007;
typedef long long ll;
int n,m,i,j,k;
ll ans=1e18,v,cnt;
priority_queue<int,vector<int>,greater<int> >e[N],s[N],S;
int main(){
	for(scanf("%d%d",&n,&m),i=1;i<=n;++i)
	scanf("%d%d",&j,&k),s[j].push(k);
	for(i=1;i<=n;++i){
		while(!S.empty())S.pop();
		cnt=s[1].size();
		for(j=2;j<=m;++j)e[j]=s[j];
		for(v=0,j=2;j<=m;++j)
		while(e[j].size()>=i)
		v+=e[j].top(),e[j].pop(),cnt++;
		for(j=2;j<=m;++j)
		while(!e[j].empty())S.push(e[j].top()),e[j].pop();
		for(;cnt<i&&!S.empty();++cnt)v+=S.top(),S.pop();
		if(cnt>=i)ans=min(ans,v);
	}
	printf("%I64d\n",ans);
}

猜你喜欢

转载自blog.csdn.net/LSD20164388/article/details/81625277