ICode9

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

第一次写博客(简谈codeforces心得)orz

2020-10-31 09:34:45  阅读:277  来源: 互联网

标签:orz int 简谈 codeforces 品数 maxn mp -- include


这一周打codeforces,我发现它出题真的秒~

自己做的题实在是太少了!orz 算法很好玩,都大二了,要加油鸭!冲冲冲

一周刷题记录挂上:

div2的A、B和div3的A、B、C差不多都考思维,每道题都很巧!

div2的C和div3的D就要用些算法知识了(很多都是当场问的dalao

简单写一些dalao教我的题目的解题思路吧!

1.1435C Perform Easily

题目链接:https://codeforces.com/contest/1435/problem/C
题目大意:

吉他上有6根弦,给你a1,a2 , a3 , a4 , a5 , a6 每个弦上附上一个数字,然后给你n (1 ≤ n ≤ 100000)个数,b1, b2, ..., b3 (1 ≤ bi ≤ 109), 并且满足任意b大于a,每个数字都可以放在任意的弦上,

弦数(ai) + 品数 = bj 找所有的数组b都放到弦上后的最大和最小的品数的差值的最小值。

写个题意好累orz)

样例解释:

第一行是各个弦的数字a: 1 1 2 2 3 3

第二行是要放到弦上的数字的数量n: 7

第三行是放上去的n个数字b: 13 4 11 12 11 13 12(有重复数字,放在一个点上即可)

13 --> 放在数为3的弦上 品:10

12 --> 放在数为3的弦上 品:9

12 --> 放在数为3的弦上 品:8

4 --> 放在数为1的弦上 品:3

最大品数和最小品数的差值: 7

解题思路:

因为有1e5个数,可以考虑暴力将所有的数字放在所有的弦上,求距离(O(6e5))放在一个pair数组中,pair的first存品数(方便sort排序),second存j(b数组的下标)。

利用sort使品数排序,然后进行一次从左向右遍历。找到n个下标都存在时的最大和最小值(相当于动态变化的一个n个数字的数组),不断根据它更新答案,找到最小的数组中的最大值-最小值。

这个动态数组找最大和最小值,dalao教我了两种方法:线段树 和 用map(自动排序) 存

而我线段树懒得写(忘的差不多了orz),就用的map。

map存储的是该品数的个数,并且用一个数组v存储当前该数字的数值,当需要更新该数字品数时,把之前的品数v[bb]从v中找到,并在map[v[bb]]--,当改品数的值为0的时候,要erase该品数这点很重要),当num==n的时候,就可以更新ans了!

写完一个题了,耶耶耶!

AC代码:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <utility>
#include <map>
using namespace std;
int a[6]; 
map<int,int> mp;
const int maxn = 1e5+5;
int b[maxn];
typedef pair<int,int> PII;
PII s[maxn*6];
int v[maxn];
int main(){
	for(int i=0;i<6;i++){
		scanf("%d",&a[i]);
	}
	int n;
	cin>>n;
	for(int i=0;i<n;i++){
		scanf("%d",&b[i]);
	} 
	int len=0;
	for(int i=0;i<6;i++){
		for(int j=0;j<n;j++){
			s[len++]={b[j]-a[i],j};
		}
	}
	sort(s,s+len);
	int num=0;
	int ans=0x3f3f3f3f;
	for(int i=0;i<len;i++){
		int aa=s[i].first;
		int bb=s[i].second;
		if(v[bb]==0){
			num++;
		}
		if(mp[v[bb]]>0)
			mp[v[bb]]--;
		mp[aa]++;
		if(mp[v[bb]]==0){
			mp.erase(v[bb]);
		}
		v[bb]=aa;
		auto it=mp.begin();
		if(num==n){
			ans=min(ans,aa-it->first);
		}
	}
	cout<<ans<<endl;
	return 0;
}

C题太难写了,写个B题吧。思路依然很巧妙~

2.1421B题 Putting Bricks in the Wall

题目链接:https://codeforces.com/contest/1421/problem/B
题目大意:

一个人从S出发,想到达F,他可以上下左右进行移动,但只能选择0或者1进行移动(一旦选择,就不能更改)。必须防止他到达F,你最多可以更改2次(0改成1,或1改成0)。

样例解释:
4
S010
0001
1000
111F
->
S010
0001
1001
111F
//选择 1 或者 0 都无法到达 F
解题思路:

只需要把他的入口和出口改成相反的就可以了(入口全0,出口全1 或 入口全1,出口全0),仔细想一下,真是最多只需要两次改变。(我竟第一眼想的是dfs,bfs,老憨批了┮﹏┭)。

AC代码:

代码可能有点乱。

#include <iostream>
using namespace std;
const int maxn = 205;
char mp[maxn][maxn];
int main(){
	int t;
	cin>>t;
	int n;
	while(t--){
		cin>>n;
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				cin>>mp[i][j];
			}
		}
		char a=mp[1][0];
		char b=mp[0][1];
		
		char c=mp[n-1][n-2];
		char d=mp[n-2][n-1];
		if(a==b&&c==d){//0 1
			if(a==c){
				cout<<"2"<<endl;
				cout<<"1 2"<<endl;
				cout<<"2 1"<<endl; 
			}else{
				cout<<"0"<<endl;
			}		
		}
		else{
			if(a==d&&b==c){
				cout<<"2"<<endl;
				cout<<"1 2"<<endl;
				cout<<n-1<<' '<<n<<endl;
			}   
			else if(a==c&&b==d){
				cout<<2<<endl;
				cout<<"1 2"<<endl;
				cout<<n<<' '<<n-1<<endl;
			}
			else if(a==b){
				cout<<"1"<<endl;
				if(c==a){
					cout<<n<<' '<<n-1<<endl;
				}
				if(d==a){
					cout<<n-1<<' '<<n<<endl;
				}
			}
			else if(c==d){
				cout<<1<<endl;
				if(a==c){
					cout<<"2 1"<<endl;
				}
				if(b==c){
					cout<<"1 2"<<endl;
				}
			}
			
		}
	}
	return 0;
}

标签:orz,int,简谈,codeforces,品数,maxn,mp,--,include
来源: https://www.cnblogs.com/AC673523745/p/13905172.html

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

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

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

ICode9版权所有