2024 暑假友谊赛 2

Tiling Challenge

Problem - 1150B - Codeforces

四川省赛原题。

开一个二维字符数组和一个二维int数组。判断输入情况,如果这个点是'.'并且没有被判断过,那么就判断他的上下左右,记录‘.’出现的次数,如果是4次,那么这些点就组成了一个十字架。在int数组里把这些点全都++,最后看是不是所有的'.'在int数组里都被标记而且都是1。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define inf 0x3f3f3f3f
#define pii pair<int,int>
char a[55][55];
int b[55][55];
void solve() {
	int n;
	cin>>n;
	
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			cin>>a[i][j];
		}
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			int sum=0;
			if(a[i][j]=='.' and b[i][j]==0){
				if(a[i][j-1]=='.' and j-1>=0 and b[i][j-1]==0){
					sum++;
				}if(a[i-1][j]=='.' and i-1>=0 and b[i-1][j]==0){
					sum++;
				}if(a[i+1][j]=='.' and i+1<n and b[i+1][j]==0){
					sum++;
				}if(a[i][j+1]=='.' and j+1<n and b[i][j+1]==0){
					sum++;
				}
			}
			if(sum==4){
				b[i][j-1]++;
				b[i+1][j]++;
				b[i-1][j]++;
				b[i][j]++;
				b[i][j+1]++;
			}
		}
	}
	int k1=0;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			if(b[i][j]!=1 and a[i][j]=='.'){
				k1=1;
			}
		}
	}
	if(k1==0){
		cout<<"YES"<<endl;
	}else{
		cout<<"NO"<<endl;
	}
}

signed main() {
	ios::sync_with_stdio ( false );
	cin.tie ( nullptr );
	cout.tie ( nullptr );
	int oyyo = 1;
	//cin >> oyyo;
	while ( oyyo-- ) {
		solve();
	}
	return 0;
}

D. Walk on Matrix

这个题,🧠,分水岭开始了。

先看看题里给出的意思,这个玩意,和我一样不会dp的玩意,它是什么意思。

题里要的是让求出‘与运算’和的最大值,这个就和加乘运算不一样,他不是越大越好,或者越小越好,而是和二进制位数有关,这个就是他的漏洞,如果它&出的结果是个10000000的二进制,他很大,但是他和111111&的结果呢,0,零蛋嘞,这样他就会在过程中产生差错。

我们要的就是把他尽量往大的数那里去引导。这个大数还要有特点,那就是尽量要是1000000形式。这样就很容易去实现&后结果为零,要实现这个引导。我们可以“通过别人的题解”看到最多有三个行列就够了。因为可以用左上角4个数就产生错误的结果,再扩展一个边,用来把两个过程的结果确定为0和k。这就和题目要求一致,而且不用费力再去考虑&规律。

至于为什么三个行列就够了。(二进制位没有数,容易理解就够了,乱打的)

你看,你要从最左上角开始走,然后只有两种移动方式。下👇和👉右。你把一个很大的二进制是11111111的数放在最左上角(起点),这样子他去移动,只会使位数减少,而且只会去完全继承新的数(因为是&),你把一个二进制是10000000的,而且比左上角的数小,比要求的k值大的数,放在(1,2)的位置。这些数都可以通过位移运算得到,然后把要求的k值放在(2,1)位置,把左上角的数复制放到(2,2)位置,这样,(2,2)位置,照题目这个玩意的运算,就会变成100000000,因为他会继承一个大的数而不是去考虑二进制。但按我们的方式,他会去继承k,(没事,你接着看)。然后我们把k值复制放在(3,2)位置,再复制放到(3,3)的终点位。其他两个位置去放0,你来看。

第一步按他的(1,2)不变,(2,1)不变,(2,2)变成10000,(1,3)10000,(2,3)0保持,(3,1)0保持,(3,2)的k去继承的,只能变成0,因为,左边是0,上边和他二进制位相同的位值还是0,然后(3,3)去继承,(承个🥚)它只能是0。

但按我们的方法:

第一,(2,1)继承(1,1)k保持不变,第二,(2,2)继承k,变成k,第三,(3,2)继承变成k,最后(3,3)继承k&k=k。结果差k。🐂🖊。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define inf 0x3f3f3f3f
#define pii pair<int,int>

void solve() {
	int k;
	cin>>k;
	if(k==0){
		cout<<1<<" "<<1<<endl;
		cout<<"300000"<<endl;
		return;
	}
	int k0=300000;
	int w=0;
	while(k0!=0){
		k0>>=1;
		w++;
	}
	int k1=1,k2=1;
	for(int i=0;i<w-2;i++){
		k1<<=1;
		k1|=1;
	}
	for(int i=0;i<w-1;i++){
		k2<<=1;
	}
	k2-=1;
	int k22=1;
	for(int i=0;i<w-1;i++){
		k22<<=1;
	}
	int k220=1;
	for(int i=0;i<w-2;i++){
		k220<<=1;
	}
	k22-=k220;
	cout<<3<<" "<<3<<endl;
	cout<<k1<<" "<<k22<<" "<<k22<<endl;
	cout<<k<<" "<<k2<<" "<<0<<endl;
	cout<<0<<" "<<k<<" "<<k<<endl;
}

signed main() {
	ios::sync_with_stdio ( false );
	cin.tie ( nullptr );
	cout.tie ( nullptr );
	int oyyo = 1;
	//cin >> oyyo;
	while ( oyyo-- ) {
		solve();
	}
	return 0;
}

⛏🗡,告辞。

D - All Assign Point Add

D - All Assign Point Add (atcoder.jp)

你看这个垃圾题,他卡操作1的数组赋值。

map解决一切。

用map记录现在存在的数(first-下标,second-数值),然后对于操作一,清空map,只记录一个更改后的数,对于操作二,如果,这个下标在map中存在,那么就输出下标对应的值,如果没有,那这个就是被清空后还没记录了。输出记录的数字,然后把最后改好的数插入进去。对于操作三同样,没找到,就输出“shu”,找到了就输出代表值。哦几百块。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define inf 0x3f3f3f3f
#define pii pair<int,int>

void solve() {
	map<int,int>u;
	int n;
	cin>>n;
	vector<int>a(n+1);
	for(int i=1;i<=n;i++){
		cin>>a[i];
		u[i]=a[i];
	}
	
	int q;
	cin>>q;
	int shu=0;
	for(int i=0;i<q;i++){
		int x;
		cin>>x;
		if(x==1){
			int y;
			cin>>y;
			u.clear();
			shu=y;
		}if(x==2){
			int b,y;
			cin>>b>>y;
			if(u.find(b)==u.end()){
				u[b]=shu+y;
			}else{
				u[b]+=y;
			}
		}
		if(x==3){
			int y;
			cin>>y;
			if(u.find(y)==u.end()){
				cout<<shu<<endl;
			}else{
				cout<<u[y]<<endl;
			}
		}
	}
	
}

signed main() {
	ios::sync_with_stdio ( false );
	cin.tie ( nullptr );
	cout.tie ( nullptr );
	int oyyo = 1;
	//cin >> oyyo;
	while ( oyyo-- ) {
		solve();
	}
	return 0;
}

B - Reserve or Reverse

B - Reserve or Reverse (atcoder.jp)

🐕的没目题,普及,我给他🐎糖丸了。(垃圾的🦅🐟,垃圾的🍚译)

你有一个数,还有等长的字符串。你有一个绝对上升的序列,序列有2*k个数,这个k不给你。根据序列,字符串可以做出1<->2*k,2<->2*k-1.........这样的操作。问你操作完后最大的序列是啥。

记得忽略哦,佬。我按等间隔取数字写的。虽然读题后仍然不会写,不妨碍我骂街。

感谢日本码友提供的代码。

首先,开头的字符一定要换成字符串里的最小值。然后这个最小字符的下标要保存的尽量大,以便我们可以进行最多的操作。用双指针。如果开头的数字就是当前可改动的最小值,直接跳过,不然就去最小字符出现的坐标之前去找,如果是当前记录的可找到的最小字符,那么直接break替换,这样可以继续维持区间最大,否则,将当前可找到的最小字符更新。再继续找。直到l遇到r。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define inf 0x3f3f3f3f
#define pii pair<int,int>

void solve() {
	int n;
	cin >> n;
	string s;
	cin >> s;
	char min1 = 'z';
	int k1 = 0;
	for (int i = 0; i < n; i++) {
		if (min1 >= s[i]) {
			k1 = i;
			min1 = s[i];
		}
	}
	char c = min1;
	int l = 0, r = k1;
	while (l < r) {
		while (s[l] == c) {
			l++;
		}
		int flag = 0;
		for (int i = r; i > l; i--) {
			if (s[i] == c) {
				swap(s[l], s[i]);
				l++;
				r = i - 1;
				flag = 1;
				break;
			}
		}
		if (!flag) {
			c++;
		}
	}
	cout << s << endl;
	return;


}

signed main() {
	ios::sync_with_stdio ( false );
	cin.tie ( nullptr );
	cout.tie ( nullptr );
	int oyyo = 1;
	//cin >> oyyo;
	while ( oyyo-- ) {
		solve();
	}
	return 0;
}

woshisb

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值