zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校训练营(第三场) H Sort the Strings Revision

    思路:由于是字典序,所以肯定是越前面的字符对整体的字典序的影响越大,所以我们先看最小的 (p[i]) , 假设最小的 (p[i] = st) ,并且 (d[i] != st \% 10)

    如果 (d[i] < st \% 10) , 那么 (s_1 - s_i) > (s_{i + 1} - s_n) ,大于则同理,这个手写一个样例就会理解,这样我们就把所有字符串分成了两个互相独立的字符串

    集合,对于每个字符串子集,都可以用同样的办法处理,唯一的难点是要找出连续区间内最小的 (p[i]) ,这个可以用笛卡尔树处理,其实也可以线段树,

    不过会被卡好像(队友试过)。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn = 2e6 + 60;
    const int MOD = 1000000007;
    int n;
    int p[maxn], d[maxn], ls[maxn], rs[maxn];
    
    int stk[maxn], top;
    void dikaer(){
        top = 0;
        for(int i = 0; i < n; i++){
            if(d[i] == p[i] % 10) {
                continue;
            }
            int k = top;
            while(k > 0 && p[stk[k]] > p[i]) k--;
            if(k) rs[stk[k]] =  i;
            if(k < top) ls[i] = stk[k + 1];
            stk[++k] = i;
            top = k;
        }
    }
    
    LL pos[maxn];
    void dfs(int le, int ri, int st){
        if(le == ri) return ;
        if(st == -1){
            for(int i = 0; i < ri - le + 1; i++){
                pos[le + i] += i;
                pos[le + i + 1] -= i;
            }
            return ;
        }
        if(d[st] > p[st] % 10){
            dfs(le, st, ls[st]);
            dfs(st + 1, ri, rs[st]);
            pos[st + 1] += (st - le + 1);
            pos[ri + 1] -= (st - le + 1);
        } else if(d[st] < p[st] % 10){
            dfs(le, st, ls[st]);
            dfs(st + 1, ri, rs[st]);
            pos[le] += (ri - st);
            pos[st + 1] -= (ri - st);
        }
    }
    
    int main()
    {  
        int t;
        scanf("%d", &t);
        while(t--){
            scanf("%d", &n);
            int seed, a, b, mod;
            scanf("%d%d%d%d", &seed, &a, &b, &mod);
            int nsed = seed;
            for(int i = 0; i <= n; i++){
                stk[i] = -1;
                pos[i] = 0;
                ls[i] = rs[i] = -1;
                p[i] = i;
            }
            for(int i = 1; i < n; i++){
                swap(p[nsed % (i + 1)], p[i]);
                nsed = (1LL * nsed * a + b) % mod; 
            }
            scanf("%d%d%d%d", &seed, &a, &b, &mod);
            nsed = seed;
            for(int i = 0; i < n; i++){
                d[i] = nsed % 10;
                nsed = (1LL * nsed * a + b) % mod;
            }
            dikaer();
            dfs(0, n, stk[1]);
            for(int i = 1; i <= n; i++){
                pos[i] += pos[i - 1];
            }
            LL x = 1;
            LL ans = 0;
            for(int i = 0; i <= n; i++){
                ans = (1LL * ans + 1LL * pos[i] * x % MOD) % MOD;
                x = 10000019LL * x % MOD;
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    C语言初学者代码中的常见错误与瑕疵(22)
    ANSI C (83)和87 ANSI C 这两个标准存在么?
    常见的认证
    python入门(一)
    Altium Designer重装后图标都变白板或都变一样的解决方法
    转:关于S参数的一些理解
    射频与微波测量之S参数
    驻波比
    PCB特征阻抗计算
    函数的形参(非引用形参、指针形参、引用形参)
  • 原文地址:https://www.cnblogs.com/PCCCCC/p/13380933.html
Copyright © 2011-2022 走看看