CodeForces 1020C

本文提供了一道CodeForces1020C题目的解题思路及代码实现,采用直接模拟的方法解决小数据范围问题,并特别注意了联赛中可能出现的数据点细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CodeForces 1020C
这 题 其 实 挺 好 像 , 发 现 数 据 范 围 很 小 , 直 接 模 拟 就 行 了 这题其实挺好像,发现数据范围很小,直接模拟就行了
b u t 这 题 我 不 是 在 C F 上 打 的 , 看 不 到 数 据 点 , 有 个 细 节 真 的 没 想 到 but这题我不是在CF上打的,看不到数据点,有个细节真的没想到 butCF

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;

typedef long long ll;
const int N=3010;
int n,m,mx=0,mn=1e9+5;
int p[N],c[N];
ll sum[N][N];
vector <int> val[N];
vector <int>::iterator it; 
int tp[N];
bool ff[N];
int stat[N];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d%d",&p[i],&c[i]);
		val[p[i]].push_back(c[i]);
	}
	for(int i=1;i<=m;i++){
		if(val[i].empty()) continue;
		sort(val[i].begin(),val[i].end());
		int j=0;
		int len=val[i].end()-val[i].begin();
		if(i!=1)mx=max(mx,(len));
		for(it=val[i].begin();it<val[i].end();it++){
			sum[i][++j]=sum[i][j-1]+(*it);
		}
	}
	for(int i=1;i<=m;i++){
	    if(!val[i].empty())mn=min(mn,(*val[i].begin()));
	}
	int s1=val[1].size();//真心希望联赛不要这么坑,真的没有想到还能这样,要不是上CF看原数据点,我觉得我调十天都调不出来 
	if(mx==0&&(!val[1].empty())){
		puts("0");
	    exit(0);
	}
	if(mx==0){
		printf("%d",mn);
		exit(0);
	}
	if(s1>mx){
		puts("0");
		exit(0);
	}
	ll ans=1234567890000000;
	for(int i=s1;i<=mx+1;i++){
		ll sums=0;
		int s=s1;
		memset(ff,0,sizeof(ff));
		bool flag=false;
		for(int j=2;j<=m;j++){
			int siz=val[j].end()-val[j].begin();
			if(siz>=i){
				ff[j]=1;stat[j]=siz-i+2;
				sums+=sum[j][siz-i+1];
			    s+=siz-i+1;
			}
			if(s>i){
				flag=true;
				break;
			}
		}
		if(flag){
			continue;
		}
		if(s<i)
	    {
	    	memset(tp,0,sizeof(tp));
	    	int cnt=0;
	    	for(int j=2;j<=m;j++){
	    		if(ff[j]){
	    			it=val[j].begin()+stat[j]-1;
	    			if(it<val[j].end()){
	    				for(it;it<val[j].end();it++){
	    					tp[++cnt]=*it;
	    				}
	    			}
	    			continue;
	    		}
	    		for(it=val[j].begin();it<val[j].end();it++){
				   tp[++cnt]=*it;
			    }
	    	}
	    	sort(tp+1,tp+cnt+1);
	    	int ttp=i-s;
	    	for(int i=1;i<=(ttp);i++){
	    		sums+=tp[i];
	    	}
	    }
	
		ans=min(ans,sums);
	}
	printf("%lld",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值