Tiling Challenge
四川省赛原题。
开一个二维字符数组和一个二维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