Problem - 1150B - Codeforces
小C是重度强迫症晚期患者,如果某些图形无法按照他的想法排列,那么他就会迎来他的末日。某天小C来到了心心念念的女神家里(绝对不可能是女装大佬,绝对不可能),他发现地砖有两种颜色组成,分别是白色和绿色。小C对女神家里的一切都充满好奇,经过他不懈的研究,终于发现绿色地砖是白色地砖涂了绿色涂料变成的,这使他大为震惊,但是这些都不重要,主要是他家里的地砖是由十字形的绿色地砖组成,只要能证明女神家的地砖也是由一个个绿色十字组成,那么他就会认为女神和他很般配,如果不能那么他就会迎来强迫症末日,绿色十字如下图所示:
女神家的地砖有n行n列,总共n2𝑛2块地砖。对于一个绿色十字,小C认为必须由5块地砖组成,而且两个十字间不可以共用绿色地砖,由于女神家非常大,小C的强迫症末日一时间竟不知道要不要降临,所以需要你编程进行判断。
简单的暴力就可以了;
#include<bits/stdc++.h>
using namespace std;
#define int long long
char mp[55][55];
int n;
int dx[5]={0,0,0,1,-1};
int dy[5]={0,1,-1,0,0};
signed main(){cin>>n;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){cin>>mp[i][j]; }}int sum=0;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){sum=0;for(int k=1;k<=4;k++){if(mp[i][j]=='.'){int xx=i+dx[k];int yy=j+dy[k];if(xx>0&&xx<=n&&yy>0&&yy<=n&&mp[xx][yy]=='.'){sum++;}}}if(sum==4){for(int k=1;k<=4;k++){if(mp[i][j]=='.'){int xx=i+dx[k];int yy=j+dy[k];if(xx>0&&xx<=n&&yy>0&&yy<=n&&mp[xx][yy]=='.'){mp[xx][yy]='#';}}}mp[i][j]='#';}}}for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(mp[i][j]=='.'){cout<<"NO"<<endl;return 0;}}}cout<<"YES"<<endl;return 0;
}
D - All Assign Point Add (atcoder.jp)
题意:给你一个长度为n的数组,你有Q次操作,
有三种类型的操作:
1 x:将数组所有的值全部都变为x;
2 x y:将y加入到数组下标为x的位置(数组下标从1开始)
3 x :输出下标为x的数组中值;
数据范围是2e5;
题解,当执行操作1的时候不用全部都更新,只用开一个数组记录执行操作2 / 3 之前有无将数更新为x即可;
#include<bits/stdc++.h>
using namespace std;
#define int long long
int a[200005];
int b[200005];
queue<int>one;
queue<pair<int,int>>two;
queue<int>three;
queue<int>xuhao;
signed main(){int n;cin>>n;for(int i=1;i<=n;i++){cin>>a[i];}int Q;cin>>Q;int x=0,f=0;while(Q--){int op;cin>>op;if(op==1){cin>>x;f++;}else if(op==2){int y,u;cin>>y>>u;if(b[y]!=f){b[y]=f;a[y]=x+u;}else{a[y]+=u;}}else if(op==3){int p;cin>>p;if(b[p]==f)cout<<a[p]<<endl;else {b[p]=f;a[p]=x;cout<<a[p]<<endl;}}}}
Problem - 1332D - Codeforces
题解:构造一个矩阵,找找其中规律,要让自己的算法和正确答案之间的差值不大于k;
因为k的取值范围是1e5转换成二进制就是2的17次方,所以将1<<17位,接着我们来构造一个矩阵:
2*2的矩阵可以吗,显然不行,这样的话小明的算法和正确答案是一模一样的,那我们构造一个2*3的矩阵,
ans=1<<17;
我们需要让算法的结果为0,正确答案为k即可
矩阵:
ans+k ans 0
k ans+k k
按照小明的算法得到的结果就是
ans+k ans 0
k ans(max(ans,k)) 0
而正确答案是不用取最大,就取k,最后结果就是最大值k;
他们之间就像相差k;
#include<bits/stdc++.h>
using namespace std;
#define int long longsigned main(){int k;cin>>k;int ans=(1<<17);cout<<2<<' '<<3<<endl;cout<<ans+k<<" "<<ans<<" "<<0<<endl;cout<<k<<" "<<ans+k<<" "<<k<<endl;return 0;
}
[ARC134B] Reserve or Reverse - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
什么是子序列:
从最初序列通过去除某些元素但不打乱余下元素的相对位置(在前或则在后)而形成的新序列
从第一个字符开始遍历元素,找到从a到h[i]的字母,一旦发现能找到就交换并且缩短距离右边界,
一些小细节就是找到的字母中一定不能超过r边界,不然就不满足总序列的条件;其次我们用栈区存元素出现的下标,是为了让r在尽可能的范围内最小化缩短,这样可能可以交换更多的字母;
#include <bits/stdc++.h> using namespace std;
string s;
vector<int> v[30];
int N;
int main(){ cin >> N >> s; for(int i=0; i<N; i++)v[s[i] - 'a'].push_back(i); int r = N - 1; // 初始化r为字符串s的最后一个字符的索引 for(int l=0; l<N; l++){ int u = -1; // 用于存储找到的符合条件的字符的索引,初始化为-1 // 遍历从'a'到当前字符s[l]之间的所有字母(按ASCII码顺序) for(int j=0; j<s[l]-'a' && u == -1; j++){ // 移除当前vector中索引大于r的元素,因为这些元素在s[r]之后,不可能与s[l]交换 while(!v[j].empty() && v[j].back() > r) v[j].pop_back(); // 如果当前vector不为空,且最后一个元素的索引在[l+1, r]之间(即在当前字符s[l]之后但在s[r]之前或相等),则更新u if(!v[j].empty() && v[j].back() <= r && v[j].back() > l){ u = v[j].back(), v[j].pop_back(); // 更新u并移除该元素,因为已经找到并准备交换 } } // 如果找到了符合条件的字符(即u != -1),则交换s[l]和s[u](或s[r],因为r在循环开始前被设置为u) if(u != -1){ r = u; // 更新r为找到的字符的索引 swap(s[l], s[r]); // 交换字符 } } cout << s; // 输出排序后的字符串 return 0;
}