2021/11/27 总结
作者:互联网
一天跟了三场比赛;记录一下部分题目;
https://ac.nowcoder.com/acm/contest/24803/D
题意
nxn的矩阵只能旋转最外面一层,问最后能不能使得整体有序;
题解
可以把最外层全部抠出来,然后可以观察到,他和有序的最外层的最小表示实际上是一样的,如果外面相等,里面可以按照顺序判断,复杂度n*n,(数据范围只有10,感觉可以开到1000.。。)
const int N = 20;
int g[N][N];
int d[N][N];
vector<int> v;
vector<int> get_min(vector<int>& s) {
int n = s.size();
for (int i = 0; i < n; i++) s.push_back(s[i]);
int i = 0, j = 1, k = 0;
while (i < n and j < n) {
for (k = 0; s[i + k] == s[j + k] and k < n; k++);
if (k == n) break;
if (s[i + k] > s[j + k]) {
i += k + 1;
if (i == j) i++;
} else {
j += k + 1;
if (i == j) j++;
}
}
k = min(i, j);
vector<int> v;
for (int i = k; i < k + n; i++) v.push_back(s[i]);
return v;
}
int n;
vector<int> init1() {
vector<int> v;
for (int i = 1; i <= n; i++) {
v.eb(d[1][i]);
}
for (int i = 2; i <= n; i++) {
v.eb(d[i][n]);
}
for (int i = n - 1; i >= 1; i--) {
v.eb(d[n][i]);
}
for (int i = n - 1; i >= 2; i--) {
v.eb(d[i][1]);
}
return v;
}
void solve() {
cin >> n;
int idx = 0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>d[i][j];
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
g[i][j] = ++idx;
}
}
for (int i = 1; i <= n; i++) {
v.eb(g[1][i]);
}
for (int i = 2; i <= n; i++) {
v.eb(g[i][n]);
}
for (int i = n - 1; i >= 1; i--) {
v.eb(g[n][i]);
}
for (int i = n - 1; i >= 2; i--) {
v.eb(g[i][1]);
}
auto v1 = init1();
if (get_min(v) == get_min(v1)) {
int cnt=0;
bool ok=true;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
++cnt;
if(i==1 or i==n or j==1 or j==n) continue;
if(d[i][j]!=cnt) ok=false;
}
}
if(ok) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
} else cout << "NO" << endl;
}
https://ac.nowcoder.com/acm/contest/24803/B
题意
问一个字母出现k次且最短的序列长度是多少
题解
可以双指针也可以二分
#include <bits/stdc++.h>
#define eb emplace_back
#define divUp(a,b) (a+b-1)/b
#define mkp(x,y) make_pair(x,y)
#define all(v) begin(v),end(v)
#define int long long
#define deb(x) cout<<#x<<" "<<x<<endl
#define fi first
#define se second
using namespace std;
typedef pair<int, int> pii;
bool checkP2(int n) {return n > 0 and (n & (n - 1)) == 0;};
const int N=100010;
char s[N];
int c[30];
int cnt[30];
void solve() {
int m;
cin>>(s+1);
int n=strlen(s+1);
memset(c,0,sizeof c);
cin>>m;
int res=2e9;
for(int i=1;i<=n;i++) c[s[i]-'a']++;
for(int i=0;i<26;i++){
if(c[i]>=m){
memset(cnt,0,sizeof cnt);
for(int j=1,k=1;j<=n;j++){
while(cnt[i]<m and k<=n) {
if(s[k]==i+'a') cnt[i]++;
k++;
}
if(cnt[i]>=m) {
res=min(res,k-j);
}
if(s[j]==i+'a') cnt[i]--;
}
}
}
if(res==2e9) cout<<-1<<endl;
else cout<<res<<endl;
}
signed main() {
std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int _; cin >> _; while (_--)
solve();
return 0;
}
https://atcoder.jp/contests/abc229/tasks/abc229_dhttps://atcoder.jp/contests/abc229/tasks/abc229_d
题意
一个序列只有x和.最多可以花费k次把.变成x,问连续x的最长序列长度是多少
题解
发现可以二分序列长度,只要再这个长度内花费小于等于k即可,利用前缀和统计x就可以知道.的个数
const int N = 200010;
char s[N];
int sum[N];
int k;
int n;
bool check(int mid) {
for (int i = mid, j = 1;i <= n;i++, j++) {
int cur = sum[i] - sum[j - 1];
int len = i - j + 1;
if (len - cur <= k) {
return true;
}
}
return false;
}
void solve() {
cin >> (s + 1)>>k;
n=strlen(s+1);
for (int i = 1;i <= n;i++) {
if (s[i] == 'X') sum[i] = 1;
sum[i] += sum[i - 1];
}
int l = 0, r = n;
while (l < r) {
int mid = (l + r + 1) >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
cout << l << endl;
}
https://atcoder.jp/contests/abc229/tasks/abc229_e
题意
给了一个图,每次按照顺序删除编号为i的点,问删除第i个点之后的连通块有多少
思路
求连通块的话很明显可以用并查集,但是每次按照顺序的话,后面删除操作比较困难,所以可以选择倒着跑,每次加进来一个点,如果发现这个点的根节点是他自己,就说明这是一个新的块,每个父节点可以使用set来记录,也方便删除,还有注意一点,加边的时候是较小的边指向较大的边,考虑较大边的时候较小边已经被删除;
int p[N];
int find(int x){
if(x!=p[x]) p[x]=find(p[x]);
return p[x];
}
set<int> s;
pii a[N];
int ans[N];
void merge(int x,int y){
int pa=find(x),pb=find(y);
if(pa!=pb){
p[pa]=pb;
s.erase(pa);
}
}
vector<int> h[N];
void solve() {
int n,m;
cin>>n>>m;
int x,y;
for(int i=1;i<=m;i++){
cin>>x>>y;
h[min(x,y)].eb(max(x,y));
}
for(int i=1;i<=n;i++) p[i]=i;
for(int i=n;i>=1;i--){
ans[i]=s.size();
if(find(i)==i) s.insert(i);
for(auto j:h[i]){
merge(i,j);
}
}
for(int i=1;i<=n;i++) cout<<ans[i]<<endl;
}
题意
给定一个矩阵,让你找到所有的正金字塔和倒金字塔,(底边是3,5,7,9.。。。);
思路
直接暴力查找,使用前缀和做优化即可
class Solution {
public:
vector<vector<int>> g,d;
int n,m;
int sum(int x,int y,int cnt){
if(x>=n or y<0 or y+cnt>=m) return 0;
if(!d[x][y]) return 0;
if(g[x][y+cnt]-g[x][y]!=cnt) return 0;
return sum(x+1,y-1,cnt+2)+1;
}
int sum1(int x,int y,int cnt){
if(x<0 or y<0 or y+cnt>=m) return 0;
if(!d[x][y]) return 0;
if(g[x][y+cnt]-g[x][y]!=cnt) return 0;
return sum1(x-1,y-1,cnt+2)+1;
}
int countPyramids(vector<vector<int>>& grid) {
d=grid;
g=grid;
m=grid[0].size();
n=grid.size();
int res=0;
for(int i=0;i<n;i++){
g[i][0]=grid[i][0];
for(int j=1;j<m;j++){
g[i][j]=grid[i][j]+g[i][j-1];
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(grid[i][j]){
res+=sum1(i,j,0)-1+sum(i,j,0)-1;
}
}
}
return res;
}
};
标签:11,cnt,27,return,int,eb,--,vector,2021 来源: https://www.cnblogs.com/koto-k/p/15614169.html