Codeforces Round 817 (Div. 4)题解ABCDEFG

Problem - A - Codeforces

题意:

输入一个字符串,请判断这个字符串是不是字符串 Timur 的一种排列。

例如:Timur ,miurT ,Trumi ,mriTu 都是正确的排列。

思路:模拟即可

// Code Start Here	
	int t;
	cin >> t;
	while(t--){
		int n;
		cin >> n;
		string s;
		cin >> s;
		map<int,int> mp;
		for(auto i : s)mp[i]++;
		if(mp['T'] == 1 && mp['i'] == 1 && mp['m']  == 1 && mp['u'] == 1&& mp['r'] == 1 && sz(mp) == 5)cout <<"Yes\n";
		else cout <<"No\n";
	}
	

Problem - B - Codeforces

题意:给定两个由 RGB 组成的字符串,R代表红色,G 代表绿色,B 代表蓝色。Vasya 有色盲症因此他无法分辨蓝色和绿色。问这两个字符串在 Vasya 眼里是否相同。

思路:根据题意蓝绿同色,模拟即可

// Code Start Here	
	int t;
	cin >> t;
	while(t--){
		int n;
		cin >> n;
		string a, b ;
		cin >> a >> b;
		for(int i = 0;i<n;i++){
			if(a[i] == 'G') a[i] = 'B';
			if(b[i] == 'G') b[i] = 'B';
		}
		bool f = true;
		for(int i = 0;i<n;i++){
			if(a[i]!=b[i]){
				f = false;
			}
		}
		if(f)cout <<"Yes\n";
		else cout <<"No\n";
	}

Problem - C - Codeforces

题意:

t 组数据,每组一个 n 表示字符串数量,之后三行每行 n 个长度为 3 的字符串,表示三个小朋友各自的字符串。

如果一个字符串只有一个小朋友有,那他得三分。如果有两个小朋友有,两人各得一分。若三人都有,不得分。

求出三个小朋友最终得分。

思路:对每个字符串判断一下在哪些里面出现过即可,这里使用了map来离散化

// Code Start Here	
	int t;
	cin >> t;
	while(t--){
		int n;
		cin >> n;
		map<string,vector<int>> mp;
		for(int i = 1;i<=3;i++){
			for(int j = 1;j<=n;j++){
				string s;
				cin >> s;
				mp[s].push_back(i);
			}
		}
		map<int,int> ans;
		for(auto [k,v]: mp){
			if((int)(v.size() == 1)){
				for(int u : v)ans[u]+=3;
			}
			else if((int)(v.size()) == 2){
				for(int u : v)ans[u] += 1;
			}
		}
		cout << ans[1] << " " << ans[2] <<" " << ans[3] <<endl;
	}

Problem - D - Codeforces

题意:

t 组数据,每组给出 n 与长度为 n 的,仅由 L ,R 构成的字符串。

其中 L 的得分为其左边的字母数量, R 的得分为其右边的字母数量,字符串得分为所有字母得分之和。

你可以修改其中的某几个字符来获得更大得分。求出修改至多 1个、2个 ...... n个字符可以获得的最大字符串得分。

思路:我们观察到需要尽量让左边变成R加右边的,右边变成L加左边的,如果本来已经是L或者R就不用浪费次数修改,双指针即可,这里使用双端队列

// Code Start Here	
	int t;
	cin >> t;
	while(t--){
		int n;
		cin >> n;
		deque<pair<char,int>> dq(n);
		vector<int> v(n+1);
		int now_val = 0;
		for(int i = 1;i<=n;i++){
			cin >> dq[i-1].first;
			dq[i-1].second = i;
			if(dq[i-1].first == 'L') v[i] = i - 1;
			else v[i] = n - i;
			now_val += v[i];
		}
		bool f = true;
		vector<int> ans;
		while(!dq.empty()){
			if(f){
				f = false;
				auto ff = dq.front();
				dq.pop_front();
				if(ff.first == 'L'){
					now_val -= v[ff.second];
					now_val += (n - ff.second);
					ans.push_back(now_val);
				}
			}
			else{
				f = true;
				auto bb = dq.back();
				dq.pop_back();
				if(bb.first == 'R'){
					now_val -= v[bb.second];
					now_val += (bb.second -1);
					ans.push_back(now_val);
				}
			}
		}
		while((int)(ans.size()) < n)ans.push_back(now_val);
		sort(ans.begin(),ans.end());
		for(int i = 0;i< n;i++)cout << ans[i] <<" ";
		cout << endl;
	}

Problem - E - Codeforces

题意:

分别给定 n 个正整数 hi​,wi​ ,有 q 次询问。

对于每次询问,输入四个整数 hs​,ws​,hb​,wb​,输出满足 hi​∈(hs​,hb​) ,wi​∈(ws​,wb​) 的 ∑hi​⋅wi​

思路:观察到1000内,首先想到On^2,再看到\sum h_i *w_i马上想到前缀和。

答案呼之欲出了,读入的时候加入一下当前点,然后二维前缀和模拟一遍即可

// Code Start Here	
	int t;
	cin >> t;
	while(t--){
		vector<vector<int>> s(1010,vector<int>(1010,0));
		int n , q;
		cin >> n >> q;
		while(n--){
			int h , w;
			cin >> h >> w;
			s[h][w] += h * w;
		}
		for(int i = 1;i<=1000;i++){
			for(int j = 1;j<=1000;j++){
				s[i][j] += s[i-1][j] + s[i][j-1] - s[i-1][j-1];
			}
		}
		while(q--){
			int hs,ws,hb,wb;
			cin >> hs >> ws >> hb >> wb;
			cout << s[hb-1][wb-1] - s[hb-1][ws] - s[hs][wb-1] + s[hs][ws] << endl;
		}
	}

Problem - 1722F - Codeforces

题意:

L形在网格纸上形如下面的前四张图片。L形正好包含三个阴影单元(用*表示),可以以任何方式旋转。

现给你一个矩形网格。确定它是否仅包含L形,其中L形不能接触边或角,也就是说网格中的每个阴影单元正好是一个L形的一部分,并且没有两个L形通过边或角相邻。

例如,上图中的最后两个网格不满足条件,因为两个L形分别通过角和边缘接触。

如果网格满足条件,则输出“YES”,否则输出“NO”。

思路:超级大模拟,把每种L的情况遍历了即可

// Code Start Here	
	int t;
	cin >> t;
	while(t--){
		int n , m;
		cin >> n >> m;
		vector<vector<bool>> a(n+10,vector<bool>(m+10,false));
		for(int i = 1;i<=n;i++){
			for(int j = 1;j<=m;j++){
				char g;
				cin >> g;
				if(g =='*')a[i][j] = true;
			}
		}
		auto dfs = [&](auto dfs,int i,int j)->void{
			if(a[i+1][j]&&a[i+1][j+1]&&!a[i-1][j-1]&&!a[i-1][j]&&!a[i-1][j+1]&&
				!a[i][j-1]&&!a[i][j+1]&&!a[i][j+2]&&!a[i+1][j-1]&&!a[i+1][j+2]&&
				!a[i+2][j-1]&&!a[i+2][j]&&!a[i+2][j+1]&&!a[i+2][j+2]){
				a[i][j]=a[i+1][j]=a[i+1][j+1]=0;
				return ;
			}
			if(a[i+1][j-1]&&a[i+1][j]&&!a[i-1][j-1]&&!a[i-1][j]&&!a[i-1][j+1]&&
				!a[i][j-2]&&!a[i][j-1]&&!a[i][j+1]&&!a[i+1][j-2]&&!a[i+1][j+1]&&
				!a[i+2][j-2]&&!a[i+2][j-1]&&!a[i+2][j]&&!a[i+2][j+1]){
				a[i][j]=a[i+1][j-1]=a[i+1][j]=0;
				return ;
			}
			if(a[i][j+1]&&a[i+1][j+1]&&!a[i-1][j-1]&&!a[i-1][j]&&!a[i-1][j+1]&&
				!a[i-1][j+2]&&!a[i][j-1]&&!a[i][j+2]&&!a[i+1][j-1]&&!a[i+1][j]&&
				!a[i+1][j+2]&&!a[i+2][j]&&!a[i+2][j+1]&&!a[i+2][j+2]){
				a[i][j]=a[i][j+1]=a[i+1][j+1]=0;
				return ;
			}
			if(a[i][j+1]&&a[i+1][j]&&!a[i-1][j-1]&&!a[i-1][j]&&!a[i-1][j+1]&&
				!a[i-1][j+2]&&!a[i][j-1]&&!a[i][j+2]&&!a[i+1][j-1]&&!a[i+1][j+1]&&
				!a[i+1][j+2]&&!a[i+2][j-1]&&!a[i+2][j]&&!a[i+2][j+1]){
				a[i][j]=a[i][j+1]=a[i+1][j]=0;
				return ;
			}
		};
		for(int i = 1;i<=n;i++){
			for(int j = 1;j<=m;j++){
				if(a[i][j]){
					dfs(dfs,i,j);
				}
			}
		}
		bool f = true;
		for(int i = 1;i<=n;i++){
			for(int j = 1;j<=m;j++){
				if(a[i][j])f = false;
			}
		}
		if(f)cout <<"Yes\n";
		else cout <<"No\n";
	}

Problem - G - Codeforces

题意:给定一个正整数 n,请你找出一个长度为 n 数组 a,满足数组是由互不相同的非负且小于 2^31 的整数组成,并且该数组中奇数项上元素的异或和与偶数项上元素的异或和要相等。

思路:奇数和偶数位置异或和相等是全局异或和为 0 的充要条件,那么考虑构造出前 n−1 个数,第 n 个数就可以直接推出来。直接找一个大的二次幂即可

// Code Start Here	
	int t;
	cin >> t;
	while(t--){
		int x = 0;
		int n;
		cin >> n;
		for(int i = 1;i<=n-3;i++){
			cout << i << " ";
			x ^= i;
		}
		int num = 1 << 18;
		printf("%lld %lld %lld\n",num,num<<1,x^num^(num<<1));
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值