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;
    }
    
  • 相关阅读:
    内核开发特点
    制作 patch
    sdram flash 区别
    数组名 函数名
    Html标签见解——关于position问题分组总结
    Html标签见解——margin和padding使用过程中所谓的bug问题《一》
    HTML标签见解——img
    关于float和clear
    业内杂谈——你认识“用户体验”吗?
    css控制窗口上下水平居中方案详解
  • 原文地址:https://www.cnblogs.com/PCCCCC/p/13380933.html
Copyright © 2011-2022 走看看