ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces Round #727 (Div. 2) 解题报告(A-D)

2021-09-23 07:32:52  阅读:159  来源: 互联网

标签:now int Codeforces long 727 maxn need Div include


传送门


//别问我为什么现在才发,刚刚翻存库发现了这坑还留着E题没填,懒得填了所以就改成A到D题发上了。。。

总结

感觉还好,赛场上A了ABCD题,E题想出来了思路但没来得及实现。
ABCD感觉全是思维题,用不到什么高级算法。

A. Contest Start(数学)

洛谷传送门
模拟一下,会发现整个数列分成两个部分,前部分是定值,后部分因为后面没有那么多人所以是一个等差数列。
分别求一下即可。
注意开 \(long\ long\) 防炸。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<algorithm>
using namespace std;
int k;
long long n,x,t;
int main(){
	cin>>k;
	while(k--){
		cin>>n>>x>>t;
		long long num=t/x;
		if(num>=n) cout<<(1+n-1)*(n-1)/2<<endl;
		else cout<<(1+num)*num/2+(n-num-1)*num<<endl;
	}
    return 0;
}

B. Love Song(前缀和)

洛谷传送门
其实就是把字母转化为数字后,对于每一个区间,求出:

\[\sum_{i=1}^{26}num[i]*i \]

用前缀和对每个数字进行预处理即可。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=100005;
int q,n,d[maxn][30];
string s;
int main(){
	cin>>n>>q>>s;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=26;j++){
			d[i][j]=d[i-1][j];
		}
		d[i][s[i-1]-'a'+1]++;
	}
	for(int i=1;i<=q;i++){
		int l,r,ans=0;
		scanf("%d%d",&l,&r);
		for(int j=1;j<=26;j++){
			ans+=(d[r][j]-d[l-1][j])*j;
		}
		printf("%d\n",ans);
	}
    return 0;
}

C. Stable Groups(贪心)

洛谷传送门
这个问题本质就是一个区间合并。
相当于一开始给你 \(n\) 个点,排序后左右距离 \(<=x\) 的点在一个区间内,然后你可以加入 \(k\) 个点,使得一些区间合并,要求求出最后最小的区间数量(即做多能合并的数量)。
假设 \(i\) 区间的右端点到 \(i+1\) 区间的左端点的距离为 \(cha\),则需要加入的点数为 \(ceil(\frac{cha}{x})-1\),因为 \(double\) 的范围不够,所以我们要手写一个 \(ceil\)。
这样很显然的贪心就是每次选择合并需要点数最小的两个区间进行合并。
一开始扫一遍数组把间距扔到一个数组或者优先队列里排个序即可。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=200005;
int n,ans=1;
long long k,x,a[maxn];
priority_queue<long long,vector<long long>,greater<long long> > q;
int main(){
	cin>>n>>k>>x;
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	sort(a+1,a+n+1);
	for(int i=2;i<=n;i++){
		if(a[i]-a[i-1]>x){
			q.push(a[i]-a[i-1]);
			ans++;
		}
	}
	while(!q.empty()){
		long long cha=q.top();
		q.pop();
		long long need=cha/x;
		if(need*x==cha) need--;
		if(k<need) break;
		else{
			k-=need;
			ans--;
		}
	}
	cout<<ans;
    return 0;
}

D. PriceFixed(贪心,模拟)

  • 性质一:如果有价格为 \(1\) 的并且仍需要购买的物品,一定先进行购买。
  • 性质二:不会有买已经达到购买需求的物品以获取新的价格为 \(1\) 的物品行为。

性质一很显然,性质二证明如下:
设当前某个有需求的物品的还需购买 \(j\) 个,将其降到价格为 \(1\) 所需要再购买物品数为 \(k\),则两种策略花费的价格分别为:

  • \(k\le j:k+j\) 和 \(2*k+(j-k)=k+j\),可见两者相等。
  • \(k>j:k+j\) 和 \(2*k<k+j\),可见直接购买更优。

有了这两条性质,我们可以把物品按照 \(b\) 从小到大排序,模拟一下即可。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=100005;
int n,k=1;
long long now,need,ans;
struct node{
	long long a,b;
}x[maxn];
bool cmp(node a,node b){
	return a.b<b.b;
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%lld%lld",&x[i].a,&x[i].b);
		need+=x[i].a;
	}
	sort(x+1,x+n+1,cmp);
	while(now<need){
		if(k>n) break;
		long long res=max((long long)0,min(x[k].b-now,need-now));
		now+=res;
		ans+=min(need-now,x[k].a);
		now+=min(need-now,x[k].a);
		k++;
	}
	cout<<need*2-ans;
    return 0;
}

标签:now,int,Codeforces,long,727,maxn,need,Div,include
来源: https://www.cnblogs.com/yinyuqin/p/14908661.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有