zoukankan      html  css  js  c++  java
  • 《2021牛客寒假算法基础集训营2》

    H:签到。

    F:可以发现长度就是1,2,3这些第一个不在自己i位置上的,他们自己的位置减去i。

    长度找到后就去翻转验证能不能行即可。

    本来应该是要双端队列去模拟这个过程的,暴力翻转复杂度肯定不够。

    但是懒得写队列暴力了写了下过了。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 1e5 + 5;
    const int M = 5e6 + 5;
    const LL Mod = 1e9 + 7;
    #define pi acos(-1)
    #define INF 1e9
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL x = 0,f = 1;char c = getchar();
            while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
            while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
            return x*f;
        }
    }
    using namespace FASTIO;
     
    int a[N],pos[N],pre[N],nxt[N],rev[N];//rev = 1前换到后,rev2 = 后换到前
    int main()
    {
        int n;n = read();
        for(int i = 1;i <= n;++i) a[i] = read(),pos[a[i]] = i;
        int f = 0;
        for(int i = 1;i <= n;++i) if(a[i] != i) f = 1;
        if(f == 0) printf("yes
    1
    ");
        else{
            int tag = 0,len,ok = 1;
            for(int i = 1;i <= n;++i){
                if(tag == 0){
                    if(a[i] == i) continue;
                    tag = 1;
                    len = pos[i] - i + 1;
                    for(int j = 1;j <= len / 2;++j) {
                        swap(a[i + j - 1],a[i + len - j]);
                    }
                }
                else{
                    if(a[i] == i) continue;
                    else{
                        int to = i + len - 1;
                        if(a[to] != i) {
                            ok = 0;
                            break;
                        }
                        else{
                            for(int j = 1;j <= len / 2;++j){
                                swap(a[i + j - 1],a[i + len - j]);
                            }
                        }
                    }
                }
               // printf("ronud %d
    ",i);
               // for(int i = 1;i <= n;++i) printf("%d%c",a[i],i == n ? '
    ' : ' ');
            }
            if(ok == 1){
                printf("yes
    ");
                printf("%d
    ",len);
            }
            else printf("no
    ");
        }
          //system("pause");
        return 0;
    }
    View Code

    I:线性筛。

    因为直接存会爆longlong,中间取模的话又会导致答案不对。

    所以我用了字符串来拼接,最后算值,string稍微有点慢,卡了卡常数才过了。

    其实每个值只会爆一次筛选到,所以可以连父节点边,然后树上就可以dp统计贡献即可。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 4e6 + 5;
    const int M = 5e6 + 5;
    const LL Mod = 1e9 + 7;
    #define pi acos(-1)
    #define INF 1e9
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL x = 0,f = 1;char c = getchar();
            while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
            while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
            return x*f;
        }
    }
    using namespace FASTIO;
     
    string f[N];
    LL prime[N],tot = 0,ans = 0;
    bool vis[N];
    LL cal(string s){
        LL ans = 0;
        int len = s.size();
        for(int i = 0;i < len;++i){
            ans = (ans * 10 % Mod + (s[i] - '0')) % Mod;
        }
        return ans;
    }
    void init(int NN){
        for(int i = 2;i <= NN;++i){
            if(!vis[i]){
                f[i] = to_string(i);    
                prime[++tot] = i;
                ans = (ans + i) % Mod;
            }
            for(int j = 1;j <= tot && prime[j] * i <= NN;++j){
                vis[i * prime[j]] = 1;
                f[i * prime[j]] = to_string(prime[j]) + f[i];
                ans = (ans + cal(f[i * prime[j]])) % Mod;
                if(i % prime[j] == 0) break;
            }
        }
    }
    int main()
    {
        int n;n = read();
        init(n);
        printf("%lld
    ",ans);
          //system("pause");
        return 0;
    }
    View Code

    J:这题其实不难,但是比赛中想错了。

    首先,前面几个用f[i] = f[i - 1] + f[i - 2]来即可。

    我们想要复杂度尽可能高,就需要让第一重循环i尽可能多,一开始就是这里没想清楚。

    其实后面全插入1的话并且从2开始,这样就满足1 + 1 < f[i],无法构成三角形。这样可以前面的f[i]都无法满足。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 1e5 + 5;
    const int M = 5e6 + 5;
    const LL Mod = 1e9 + 7;
    #define pi acos(-1)
    #define INF 1e9
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL x = 0,f = 1;char c = getchar();
            while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
            while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
            return x*f;
        }
    }
    using namespace FASTIO;
     
    LL f[N];
    int main()
    {
        int n;n = read();
        f[0] = 1,f[1] = 2;
        int up = 40;
        for(int i = 2;i <= n;++i){
            if(i <= up) f[i] = f[i - 1] + f[i - 2 ];
            else f[i] = 1;
        }
        for(int i = 1;i <= n;++i) printf("%d%c",f[i],i == n ? '
    ' : ' ');
          //system("pause");
        return 0;
    }
    View Code

    D:这题都往整除分块方向想了。

    其实就是个找规律。

    打表排序后可以发现,以$[sqrt{n]}$为分界,一边就是1 ~ 这个值。一边就是n / 左边的值可以得到。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 1e5 + 5;
    const int M = 5e6 + 5;
    const LL Mod = 1e9 + 7;
    #define pi acos(-1)
    #define INF 1e9
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL x = 0,f = 1;char c = getchar();
            while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
            while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
            return x*f;
        }
    }
    using namespace FASTIO;
     
    int main()
    {
        int ca;ca = read();
        while(ca--) {
            int n,x;n = read(),x = read();
            int m = sqrt(n),sz;
            if(n / m == m) sz = 2 * m - 1;
            else sz = 2 * m;
            int ma = n / x;
            if(ma <= m) printf("%d
    ",sz - ma + 1);
            else printf("%d
    ",n / ma);
        }
          //system("pause"); 
        return 0;
    }
    View Code

    E:一开始扫了一眼以为是贪心直接跳了。

    其实是bfs,这题难在建图。

    观察到y的范围很小,所以按y存,之后每个vector里按左边界升序,这样同高度的连边就很简单。

    然后对于不同高度的就用双指针去维护,因为没有交叉的面积,所以双指针可以保证每个点基本只扫一遍,这样建图复杂度在O(n)。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int N = 1e5 + 5;
    const int M = 5e6 + 5;
    const LL Mod = 1e9 + 7;
    #define pi acos(-1)
    #define INF 1e9
    #define dbg(ax) cout << "now this num is " << ax << endl;
    namespace FASTIO{
        inline LL read(){
            LL x = 0,f = 1;char c = getchar();
            while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
            while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
            return x*f;
        }
    }
    using namespace FASTIO;
     
    struct Node{
        int L,r,id;
        bool operator < (const Node a)const{
            return L < a.L;
        }
    };
    vector<Node> vec[N];
    vector<int> G[N];
    int ans[N],n;
    bool vis[N];
    int bfs(){
        queue<int> Q;
        Q.push(1);
        ans[1] = 0;
        vis[1] = 1;
        while(!Q.empty()){
            int u = Q.front();
            Q.pop();
            if(u == n) return ans[u];
            for(auto v : G[u]){
                if(!vis[v]){
                    vis[v] = 1;
                    ans[v] = ans[u] + 1;
                    Q.push(v);
                }
            }
        }
    }
    int main()
    {
        n = read();
        for(int i = 1;i <= n;++i){
            int y,L,r;y = read(),L = read(),r = read();
            vec[y].push_back(Node{L,r,i});
        }
        for(int i = 0;i < N;++i) sort(vec[i].begin(),vec[i].end());
        for(int i = 0;i < N;++i){
            if(vec[i].size() == 0) continue;
            int st = 0;
            for(int j = 0;j < vec[i].size();++j){
                if(j < vec[i].size() - 1 && vec[i][j + 1].L == vec[i][j].r){//同y相邻连边
                    int u = vec[i][j].id,v = vec[i][j + 1].id;
                    G[u].push_back(v);
                    G[v].push_back(u);
                }
                while(st < vec[i + 1].size() && vec[i + 1][st].r <= vec[i][j].L) st++;//先满足左边在里面
                while(st < vec[i + 1].size() && vec[i + 1][st].L < vec[i][j].r) {
                    int u = vec[i][j].id,v = vec[i + 1][st].id;
                    G[u].push_back(v);
                    G[v].push_back(u);
                    st++;
                }
                if(st != 0) st--;//上一层可能这个块横跨了多个块
            }
        }
        printf("%d
    ",bfs());
          system("pause"); 
        return 0;
    }
    View Code

    C:分类找规律构造。一开始以为后缀树之类的就没看。

    G:离散化模拟,其实并不需要扫描线。看码力。

    A:待补

    B:待补。

  • 相关阅读:
    map方法,以及filter方法的使用
    detach与remove区别,以及detach保留被删除的元素数据,使用
    jQuery 文档操作
    javascript 清空数组的方法
    jquery遍历数组的方式
    Oracle表空间不足处理
    css 文本超出2行就隐藏并且显示省略号
    Vim中的寄存器
    spacemacs怎样配置编辑器显示行号?
    Docker考前突击
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/14371127.html
Copyright © 2011-2022 走看看