2021/11/27 总结

2021/11/28 6:10:48

本文主要是介绍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;
}

leetcode双周赛66T4

题意

给定一个矩阵,让你找到所有的正金字塔和倒金字塔,(底边是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;
    }
};



这篇关于2021/11/27 总结的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程