zoukankan      html  css  js  c++  java
  • CodeForces Educational Codeforces Round 51 (Rated for Div. 2)

    A:Vasya And Password

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const int _inf = 0xc0c0c0c0;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL _INF = 0xc0c0c0c0c0c0c0c0;
    const LL mod =  (int)1e9+7;
    const int N = 1e5 + 100;
    char s[N];
    int main(){
        int T;
        int low, upp, dig;
        scanf("%d", &T);
        while(T--){
            scanf("%s", s);
            int len = strlen(s);
            low = upp = dig = 0;
            for(int i = 0; i < len; ++i){
                if(islower(s[i])) low++;
                else if(isupper(s[i])) upp++;
                else dig++;
            }
            if(low == 0 && upp == 0){
                s[0] = 'A';
                s[1] = 'a';
            }
            else if(low == 0 && dig == 0) s[0] = 'a', s[1] = '1';
            else if(dig == 0 && upp == 0) s[0] = '1', s[1] = 'A';
            else if(low == 0){
                if(upp > 1) {for(int i = 0; i < len; ++i) if(isupper(s[i])) {s[i] = 'a'; break;};}
                else {for(int i = 0; i < len; ++i) if(isdigit(s[i])) {s[i] = 'a'; break;};}
            }
            else if(dig == 0){
                if(upp > 1) {for(int i = 0; i < len; ++i) if(isupper(s[i])) {s[i] = '1'; break;};}
                else {for(int i = 0; i < len; ++i) if(islower(s[i])) {s[i] = '1'; break;};}
            }
            else if(upp == 0){
                if(low > 1) {for(int i = 0; i < len; ++i) if(islower(s[i])) {s[i] = 'A'; break;};}
                else {for(int i = 0; i < len; ++i) if(isdigit(s[i])) {s[i] = 'A'; break;};}
            }
            printf("%s
    ", s);
        }
        return 0;
    }
    View Code

    B:Relatively Prime Pairs

    相邻2位gcd一定为1。

    代码:

    Copy
    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const int _inf = 0xc0c0c0c0;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL _INF = 0xc0c0c0c0c0c0c0c0;
    const LL mod =  (int)1e9+7;
    const int N = 1e5 + 100;
    
    int main(){
        LL l, r;
        scanf("%lld%lld", &l , &r);
        if((r-l+1)&1) puts("NO");
        else {
            puts("YES");
            for(LL i = l; i <= r; i += 2){
                printf("%lld %lld
    ", i, i+1);
            }
        }
        return 0;
    }
    View Code

    C:Vasya and Multisets

    题意:将所有数分组,要求2个组的完美数的数量相等。

    题解:

    只有数量为1的数和数量大于2的数才会影响平衡。

    数量为2的数,如果选1个放在左边,则另一个就会放在右边。

    数量>2的数,就可以把他变成1个完美数+1个不完美数,或者是1个不完美数。

    数量为一的数,一定是完美数。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const int _inf = 0xc0c0c0c0;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL _INF = 0xc0c0c0c0c0c0c0c0;
    const LL mod =  (int)1e9+7;
    const int N = 1e5 + 100;
    int vis[N];
    int a[N];
    int ok[N];
    int main(){
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i){
            scanf("%d", &a[i]);
            ++vis[a[i]];
        }
        int n1 = 0, n2 = 0;
        for(int i = 1; i <= 100; ++i){
            if(vis[i] == 1) ++n1;
            if(vis[i] > 2) ++n2;
        }
        if(n1 & 1){
            if(n2){
                puts("YES");
                n2 = 1;
                n1 /= 2;
                for(int i = 1; i <= n; ++i){
                    if(vis[a[i]] >= 3 && n2){
                        printf("A");
                        n2--;
                    }
                    else if(vis[a[i]] == 1 && n1){
                        printf("A");
                        n1--;
                    }
                    else printf("B");
                }
            }
            else {
                puts("NO");
            }
        }
        else {
            n1 /= 2;
            puts("YES");
            for(int i = 1; i <= n; ++i){
                if(vis[a[i]] == 1 && n1){
                    printf("A");
                    n1--;
                }
                else printf("B");
            }
        }
        return 0;
    }
    View Code

    D:Bicolorings

    题意:2×m的格子,求联通块为k的方案数。

    题解:DP.

    dp[i][k][z1][z2]代表的是处理到第i个位置,有k个联通块,上面颜色为z1,下面颜色为z2的方案数。

    然后我们就可以枚举 dp[i-1]的方案,把值加到dp[i][k][z1][z2]上来。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const int _inf = 0xc0c0c0c0;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL _INF = 0xc0c0c0c0c0c0c0c0;
    const LL mod =  998244353;
    const int N = 1e3+10;
    LL dp[N][N<<1][2][2];
    int main(){
        dp[1][1][0][0] = dp[1][1][1][1] = 1;
        dp[1][2][0][1] = dp[1][2][1][0] = 1;
        int n, m;
        scanf("%d%d", &n, &m);
        for(int i = 2; i <= n; ++i){
            for(int k = 1; k <= m; ++k){
                dp[i][k][0][0] = (dp[i-1][k][0][0] + dp[i-1][k][0][1] + dp[i-1][k][1][0] + dp[i-1][k-1][1][1]) % mod;
                dp[i][k][1][1] = (dp[i-1][k][1][1] + dp[i-1][k][0][1] + dp[i-1][k][1][0] + dp[i-1][k-1][0][0]) % mod;
                dp[i][k][0][1] = (dp[i-1][k-1][0][0] + dp[i-1][k-1][1][1] + dp[i-1][k][0][1]);
                dp[i][k][1][0] = (dp[i-1][k-1][0][0] + dp[i-1][k-1][1][1] + dp[i-1][k][1][0]);
                if(k > 1){
                    dp[i][k][0][1] += dp[i-1][k-2][1][0];
                    dp[i][k][1][0] += dp[i-1][k-2][0][1];
                }
                dp[i][k][0][1] %= mod;
                dp[i][k][1][0] %= mod;
            }
        }
    //    cout << dp[2][2][0][1] << " " << dp[2][2][1][0] << " " << dp[2][4][0][1] << " " << dp[2][4][1][0] << endl;
        LL ans = 0;
        ans = dp[n][m][0][0] + dp[n][m][1][1] + dp[n][m][1][0] + dp[n][m][0][1];
        ans %= mod;
        cout << ans << endl;
        return 0;
    }
    View Code

    E:Vasya and Big Integers

    题意:问将一个字符串,分成若干段,要求每一段都的值都 <= l && <= r,求可行的方案数。

    题解:字符串hash * 二分 + DP 或者 Z-function + DP。

    方案数通过DP转移。那么我们就需要求出哪一段是可以转移到当前的。

    如果需要大于L,那么就是往前走L-len步, 然后再判断这个位置开始的字符串可以不可以作为起点,不可以就往前走一步。

    如果需要小于R,那么就是往前走R-len步,然后再判断这个位置开始的字符串是不是可以作为终点,不可以就往后走一步。

    现在的问题就是怎么判断。

    方法1,就是hash字符串之后,通过二分找到第一个hash值不相等的地方,然后再判断接来下字母的大小。

    方法2,就是通过Z-function,找到每个位置能匹配的最大长度,如果不能完全匹配,那么就判断不匹配位置的字符大小。

    接下来的问题就是前导0的问题。

    定义sum[i]为到i为止方案数的前缀和,并且不包括有0可能作为前导出现的情况,也就是说当处理到a[i]的时候,只有当a[i+1]!=0的时候我们才会把东西放进去。

    定义val[i]为i的方案数。

    那么我们就可以避免前导0的情况了。

    现在还需要考虑单独为0的情况,如果当前为‘0’,并且L = ‘0’,那么就可以 val[i] += val[i-1]。

    代码1:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const int _inf = 0xc0c0c0c0;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL _INF = 0xc0c0c0c0c0c0c0c0;
    const LL mod = 998244353;
    const int N = 1e6 + 100;
    char l[N], r[N], s[N];
    LL sum[N];
    LL v[N];
    LL base = 397;
    int Mod = 1e9+7;
    ULL Hash[N], s_val[N], l_val[N], r_val[N];
    int len1, len2, len3;
    void init(){
        Hash[0] = 1;
        for(int i = 1; i < N; ++i) Hash[i] = (Hash[i-1] * base) % Mod;
        for(int i = 1; i <= len1; ++i) s_val[i] = (s_val[i-1] * base + s[i] - '0' + 1)%Mod;
        for(int i = 1; i <= len2; ++i) l_val[i] = (l_val[i-1] * base + l[i] - '0' + 1)%Mod;
        for(int i = 1; i <= len3; ++i) r_val[i] = (r_val[i-1] * base + r[i] - '0' + 1)%Mod;
    }
    ULL G1(int ll, int rr){
        return (s_val[rr] - s_val[ll-1] * Hash[rr-ll+1]%Mod+Mod)%Mod;
    }
    ULL G2(int ll, int rr){
        return l_val[rr];
    }
    ULL G3(int ll, int rr){
        return r_val[rr];
    }
    bool check1(int lp){
        if(lp < 1) return false;
        if(G1(lp, lp+len2-1) == G2(1,len2)) return true;
        int ll = 1, rr = len2;
        while(ll <= rr){
            int mid = ll+rr >> 1;
            if(G1(lp, lp+mid-1) == G2(1,mid)) ll = mid+1;
            else rr = mid - 1;
        }
        return s[lp+ll-1] > l[ll];
    }
    bool check2(int rp){
        if(rp < 1) return true;
        if(G1(rp,rp+len3-1) == G3(1,len3)) return true;
        int ll = 1, rr = len3;
        while(ll <= rr){
            int mid = ll+rr >> 1;
            if(G1(rp,rp+mid-1) == G3(1,mid)) ll = mid+1;
            else rr = mid-1;
        }
        return s[rp+ll-1] < r[ll];
    }
    int lpos[N];
    int rpos[N];
    LL val[N];
    int main(){
        scanf("%s", s+1); scanf("%s", l+1);
        scanf("%s", r+1); len1 = strlen(s+1);
        len2 = strlen(l+1); len3 = strlen(r+1);
        init();
        int ok = 0;
        if(len2 == 1 && l[1] == '0') ok = 1;
        sum[0] = 1;
        for(int i = 1; i <= len1; ++i){
            sum[i] += sum[i-1];
            if(ok && s[i] == '0') val[i] += val[i-1];
            int lp = i - (len2-1);
            if(!check1(lp)) lp--;
            if(lp < 1) continue;
            int rp = i - (len3-1);
            if(!check2(rp)) rp++;
            if(rp < 1) rp = 1;
            if(lp < rp) continue;
            val[i] += sum[lp-1];
            if(rp-2 >= 0) val[i] -= sum[rp-2];
            val[i] = ((val[i] % mod) + mod ) % mod;
            if(s[i+1] != '0') sum[i] = (sum[i]+val[i]) % mod;
        }
        printf("%lld
    ", val[len1]);
        return 0;
    }
    /*
    156156748948919764684894891894874874891981
    1
    581684
    
    */
    View Code

    代码2:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const int _inf = 0xc0c0c0c0;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL _INF = 0xc0c0c0c0c0c0c0c0;
    const LL mod = 998244353;
    const int N = 1e6 + 100;
    char l[N], r[N], s[N];
    LL sum[N];
    LL v[N];
    LL base = 397;
    int Mod = 1e9+7;
    ULL Hash[N], s_val[N], l_val[N], r_val[N];
    int len1, len2, len3;
    int posl[N];
    int posr[N];
    int z[N*2];
    char ss[N*3];
    void init(){
        strcpy(ss, l+1);
        ss[len2] = '#';
        strcpy(ss+len2+1, s+1);
        int n = len1 + 1 + len2, j = 1;
        z[0] = n;
        int k;
        for(int i=1;i<n;i=k){
            if(j < i) j = i;
            while (j < n && ss[j] == ss[j-i]) j++;
            z[i]=j-i;
            k=i+1;
            while (k+z[k-i]<j){
                    z[k]=z[k-i];k++;
            }
        }
        for(int i = 1; i <= len1; ++i) posl[i] = z[len2+i];
        strcpy(ss, r+1);
        ss[len3] = '#';
        strcpy(ss+len3+1, s+1);
        n = len1 + 1 + len3;
        z[0] = n;
        j = 1;
        for(int i=1 ;i < n; i=k){
            if(j < i) j = i;
            while (j < n && ss[j] == ss[j-i]) j++;
            z[i]=j-i;
            k = i+1;
            while (k+z[k-i]<j){
                    z[k]=z[k-i];k++;
            }
        }
        for(int i = 1; i <= len1; ++i) posr[i] = z[len3+i];
    }
    LL val[N];
    bool check1(int p){
        if(p < 1) return false;
        if(posl[p] == len2) return true;
        return s[p+posl[p]] >= l[posl[p]+1];
    }
    bool check2(int p){
        if(p < 1) return true;
        if(posr[p] == len3) return true;
        return s[p+posr[p]] <= r[posr[p]+1];
    }
    int main(){
        scanf("%s", s+1); scanf("%s", l+1);
        scanf("%s", r+1); len1 = strlen(s+1);
        len2 = strlen(l+1); len3 = strlen(r+1);
        init();
        int ok = 0;
        if(len2 == 1 && l[1] == '0') ok = 1;
        sum[0] = 1;
        for(int i = 1; i <= len1; ++i){
            sum[i] += sum[i-1];
            if(ok && s[i] == '0') val[i] += val[i-1];
            int lp = i - (len2-1);
            if(!check1(lp)) lp--;
            if(lp < 1) continue;
            int rp = i - (len3-1);
            if(!check2(rp)) rp++;
            if(rp < 1) rp = 1;
            if(lp < rp) continue;
            val[i] += sum[lp-1];
            if(rp-2 >= 0) val[i] -= sum[rp-2];
            val[i] = ((val[i] % mod) + mod ) % mod;
            if(s[i+1] != '0') sum[i] = (sum[i]+val[i]) % mod;
        }
        printf("%lld
    ", val[len1]);
        return 0;
    }
    /*
    156156748948919764684894891894874874891981
    1
    581684
    
    */
    View Code

    F:The Shortest Statement

    题意:问2点之间最短的距离。

    题解:套路题。枚举边+lca。

    需要注意到 m-n <= 20。

    那么我们就可以枚举边了,我们先把所有的边加入进来的时候,用并查集维护联通块的信息,如果发现不加某条边也是联通的情况,就把这条边的编号存下来。

    然后我们把存下来的边枚举一遍更新所有的答案。

    然后在把所有存下来的边都ban掉,然后跑lca在更新一遍答案。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<LL,int> pll;
    const int inf = 0x3f3f3f3f;
    const int _inf = 0xc0c0c0c0;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL _INF = 0xc0c0c0c0c0c0c0c0;
    const LL mod =  (int)1e9+7;
    const int N = 1e5 + 100, M = 4e5+100;
    int pre[N];
    int head[N], to[M], nt[M], ct[M], tot, ok[M];
    void add(int u, int v, int w){
        to[tot] = v;
        ct[tot] = w;
        nt[tot] = head[u];
        head[u] = tot++;
    }
    int Find(int x){
        if(x == pre[x]) return x;
        return pre[x] = Find(pre[x]);
    }
    pll p[N];
    LL ans[N];
    vector<int> vc;
    LL d[N][2];
    
    void Dij(int u, int op){
        priority_queue<pll, vector<pll>, greater<pll> > pq;
        d[u][op] = 0;
        pq.push(pll(0,u));
        while(!pq.empty()){
            int x = pq.top().se; LL dis = pq.top().fi;
            pq.pop();
            if(d[x][op] > dis) continue;
            for(int i = head[x], v; ~i; i = nt[i]){
                v = to[i];
                if(ok[i]) continue;
                if(d[v][op] > d[x][op] + ct[i]){
                    d[v][op] = d[x][op] + ct[i];
                    pq.push(pll(d[v][op],v));
                }
            }
        }
    }
    int anc[N][20];
    LL sum[N];
    int deep[N];
    int Log = 20;
    void dfs(int o, int u){
    
        deep[u] = deep[o] + 1;
        anc[u][0] = o;
        for(int i = 1; i < Log; ++i) anc[u][i] = anc[anc[u][i-1]][i-1];
        for(int i = head[u],v; ~i; i = nt[i]){
            v = to[i];
            if(v == o || ok[i]) continue;
            sum[v] = sum[u] + ct[i];
            dfs(u,v);
        }
    }
    int lca(int u, int v){
        if(deep[u] > deep[v]) swap(u,v);
        int k = deep[v] - deep[u];
        for(int i = Log-1; i >= 0; --i)
            if((k>>i)&1) v = anc[v][i];
        if(u == v) return u;
        for(int i = Log-1; i >= 0; --i)
            if(anc[u][i] != anc[v][i])
                u = anc[u][i], v = anc[v][i];
        return anc[u][0];
    }
    LL dis(int u, int v){
        return sum[u]+sum[v] - 2*sum[lca(u,v)];
    }
    int main(){
        int n, m, q;
        scanf("%d%d", &n, &m);
        memset(head, -1, sizeof (head));
        memset(ans, INF, sizeof(ans));
        for(int i = 1; i <= n; ++i) pre[i] = i;
        int u,v,w;
        for(int i = 1; i <= m; ++i){
            scanf("%d%d%d", &u, &v, &w);
            add(u,v,w);
            add(v,u,w);
            u = Find(u), v = Find(v);
            if(u == v) vc.pb(tot-2);
            else pre[u] = v;
        }
        scanf("%d", &q);
        for(int i = 1; i <= q; ++i)
            scanf("%d%d", &p[i].fi, &p[i].se);
        for(int x : vc){
            ok[x] = 1; ok[x^1] = 1;
            memset(d, INF, sizeof(d));
            Dij(to[x], 1);
            Dij(to[x^1], 0);
            for(int i = 1; i <= q; ++i){
                ans[i] = min3(ans[i], d[p[i].fi][0]+d[p[i].se][1]+ct[x],d[p[i].fi][1]+d[p[i].se][0]+ct[x]);
            }
            ok[x] = 0; ok[x^1] = 0;
        }
        for(int x : vc) ok[x] = ok[x^1] = 1;
        dfs(0,1);
        for(int i = 1; i <= q; ++i)
            ans[i] = min(ans[i], dis(p[i].fi, p[i].se));
        for(int i = 1; i <= q; ++i)
            printf("%lld
    ", ans[i]);
    
        return 0;
    }
    View Code

    G:Distinctification

    题意:问最小花费。

    题解:线段树合并。

    我们每次插入一个点之前,先判断一下这个点是不是已经加过数了,如果加过数了我们就把这个数先往后移动,移动到没有加过数的地方。

    然后现在一定是一个没有加过数的位置了,然后我们用动态线段树维护信息,注意我们插入的位置是b的。

    然后在当前位置前面的有没有出现过数,有就和前面的合并。

    对于后面的一样处理。

    然后在合并的过程中,我们明白后面大的数一定是要到左边去的。

    所以在合并的时候就更新答案。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const int _inf = 0xc0c0c0c0;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL _INF = 0xc0c0c0c0c0c0c0c0;
    const LL mod =  (int)1e9+7;
    const int N = 5e6;
    int n;
    struct Node{
        int ls, rs, num;
        LL sum;
        Node(){
            ls = rs = num = sum = 0;
        }
    }tr[N];
    int tot;
    void Insert(int &p, int b, int l, int r){
        if(p == 0) p = ++tot;
        if(l == r) {
            ++tr[p].num;
            tr[p].sum = b;
            return ;
        }
        int m = l+r >> 1;
        if(b <= m) Insert(tr[p].ls, b, l, m);
        else Insert(tr[p].rs, b, m+1, r);
        tr[p].sum = tr[ tr[p].ls ].sum + tr[ tr[p].rs ].sum;
        tr[p].num = tr[ tr[p].ls ].num + tr[ tr[p].rs ].num;
    }
    LL ans = 0;
    int Merge(int l, int r, int px, int py){
        if(!px) return py;
        if(!py) return px;
        tr[px].num += tr[py].num;
        tr[px].sum += tr[py].sum;
        if(l != r){
            int m = l+r >> 1;
            ans = ans - tr[tr[py].rs].sum * tr[tr[px].ls].num + tr[tr[px].ls].sum * tr[tr[py].rs].num;
            tr[px].ls = Merge(l, m, tr[px].ls, tr[py].ls);
            tr[px].rs = Merge(m+1, r, tr[px].rs, tr[py].rs);
        }
        return px;
    }
    int pre[N];
    int r[N], rt[N];
    int Find(int x){
        if(x == pre[x]) return x;
        return pre[x] = Find(pre[x]);
    }
    int main(){
        int n;
        scanf("%d", &n);
        for(int i = 1; i < N; ++i){
            pre[i] = i;
            r[i] = i;
        }
        int a, b;
        for(int i = 1; i <= n; ++i){
            scanf("%d%d", &a, &b);
            if(rt[a] != 0){
                int p = Find(a);
                int rr = r[p] + 1;
                ans += 1ll * b * (rr-a);
                a = rr;
            Insert(rt[a], b, 1, n);
            if(rt[a-1] != 0){
                int lx = Find(a-1);
                r[lx] = a;
                pre[a] = lx;
                rt[lx] = Merge(1,n,rt[lx],rt[a]);
            }
            if(rt[a+1] != 0){
                int rx = Find(a+1);
                int lx = Find(a);
                r[lx] = r[rx];
                pre[rx] = lx;
                rt[lx] = Merge(1,n,rt[lx],rt[rx]);
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    平衡二叉树 JAVA实现 亲测可用
    八大排序算法 JAVA实现 亲自测试 可用!
    Java 函数传入参数后,究竟发生了什么?java函数传参数原理解析
    运行错误:应用程序无法启动因为并行配置不正确。the application has failed to start because its side-by-side configuration is incorrect 解决方法
    mysql在linux下修改存储路径
    redis订阅与发布系统
    PHP Math常量
    PHP Math函数
    php 字符串函数
    PHP数组函数
  • 原文地址:https://www.cnblogs.com/MingSD/p/10130789.html
Copyright © 2011-2022 走看看