zoukankan      html  css  js  c++  java
  • 省选测试11

    A 划分序列

    题目大意 : 把n个数分成k段,使得和最大的那一段和最小

    • 如果这个些数都是非负数或都是非正数,二分答案然后贪心的扫一遍即可

    • 可是这些数有正有负,贪心是不对的

    • 所以对于枚举的答案,找到满足最大的和小于ans的分法中能分的最多段数和最小段数,如果k在范围内说明合法

    • 找最大最小的段数就用Dp,树状数组优化一下就好了

    Code

    Show Code
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    const int N = 5e4 + 5;
    
    int read(int x = 0, int f = 1, char c = getchar()) {
        for (; c < '0' || c > '9'; c = getchar())
            if (c == '-') f = -1;
        for (; c >='0' && c <='9'; c = getchar())
            x = x * 10 + c - '0';
        return x * f;
    }
    
    int n, k, a[N], m, t1[N], t2[N], s[N], b[N], l, r;
    
    void Add1(int x, int w) {
        for (; x; x -= x & -x) t1[x] = min(t1[x], w);
    }
    
    int Ask1(int x, int ans = 1e9) {
        for (; x <= m; x += x & -x) ans = min(ans, t1[x]);
        return ans;
    }
    
    void Add2(int x, int w) {
        for (; x; x -= x & -x) t2[x] = max(t2[x], w);
    }
    
    int Ask2(int x, int ans = -1e9) {
        for (; x <= m; x += x & -x) ans = max(ans, t2[x]);
        return ans;
    }
    
    bool Judge(int mid) {
        memset(t1 + 1, 0x3f, m * 4);
        memset(t2 + 1, 0xbf, m * 4);
        int f = 0, g = 0;
        for (int i = 1; i <= n; ++i) {
            int x = lower_bound(b + 1, b + m + 1, b[s[i]] - mid) - b;
            Add1(s[i-1], f); Add2(s[i-1], g);
            f = Ask1(x) + 1; g = Ask2(x) + 1;
        }
        return f <= k && k <= g;
    }
    
    int main() {
        n = read(); k = read();
        for (int i = 1; i <= n; ++i) {
            a[i] = read(), b[i] = s[i] = s[i-1] + a[i];
            a[i] < 0 ? l += a[i] : r += a[i];
        }
        sort(b + 1, b + n + 2);
        m = unique(b + 1, b + n + 2) - b - 1;
        for (int i = 0; i <= n; ++i)
            s[i] = lower_bound(b + 1, b + m + 1, s[i]) - b;
        while (l < r) {
            int mid = 1ll * l + r >> 1;
            if (Judge(mid)) r = mid;
            else l = mid + 1;
        }
        printf("%d
    ", l);
        return 0;
    }
    

    B Ring

    题目大意 : 问一段区间内的边能否组成环

    • 双指针扫一遍,用LCT动态维护联通性,挺简单的

    Code

    Show Code
    #include <cstdio>
    #include <algorithm>
    #define Get(x) (c[f[x]][1] == x)
    #define Nroot(x) (c[f[x]][Get(x)] == x)
    
    using namespace std;
    const int N = 3e5 + 5;
    
    int read(int x = 0, int f = 1, char c = getchar()) {
        for (; c < '0' || c > '9'; c = getchar())
            if (c == '-') f = -1;
        for (; c >='0' && c <='9'; c = getchar())
            x = x * 10 + c - '0';
        return x * f;
    }
    
    int n, m, q, x[N], y[N], R[N], f[N], c[N][2], t[N], stk[N], tp;
    
    void Rotate(int x) {
        int y = f[x], z = f[y], k = Get(x);
        if (Nroot(y)) c[z][Get(y)] = x; f[x] = z;
        c[y][k] = c[x][k^1]; f[c[x][k^1]] = y;
        c[x][k^1] = y; f[y] = x;
    }
    
    void Pushdown(int x) {
        if (!t[x]) return;
        swap(c[x][0], c[x][1]); t[x] = 0;
        t[c[x][0]] ^= 1; t[c[x][1]] ^= 1;
    }
    
    void Splay(int x) {
        for (int y = x; y; y = Nroot(y) ? f[y] : 0) stk[++tp] = y;
        while (tp) Pushdown(stk[tp--]);
        while (Nroot(x)) {
            int y = f[x];
            if (Nroot(y)) Get(x) == Get(y) ? Rotate(y) : Rotate(x);
            Rotate(x);
        }
    }
    
    void Access(int x) {
        for (int y = 0; x; y = x, x = f[x])
            Splay(x), c[x][1] = y;
    }
    
    void Mroot(int x) {
        Access(x); Splay(x); t[x] ^= 1;
    }
    
    int Froot(int x) {
        Access(x); Splay(x);
        while (c[x][0]) x = c[x][0];
        return x;
    }
    
    void Link(int x, int y) {
        Mroot(x); f[x] = y;
    }
    
    void Cut(int x, int y) {
        Mroot(x); Access(y); Splay(y); 
        //if (c[y][0] == x && !c[x][1])
        f[x] = c[y][0] = 0;
    }
    
    int main() {
        n = read(); m = read(); q = read();
        for (int i = 1; i <= m; ++i)
            x[i] = read(), y[i] = read();
        for (int l = 1, r = 1; l <= m; ++l) {
            for (; r <= m && Froot(x[r]) != Froot(y[r]); ++r)
                Link(x[r], y[r]);
            Cut(x[l], y[l]); R[l] = r;
        }
        while (q--) {
            int l = read(), r = read();
            puts(R[l] <= r ? ">_<" : "QAQ");
        }
        return 0;
    }
    

    C Match

    • 经过题解的化简就成了代码里的式子,但没看懂咋化的

    Code

    Show Code
    #include <cstdio>
    
    using namespace std;
    const int M = 1e9 + 7;
    
    int Pow(int a, int k, int ans = 1) {
        for (; k; k >>= 1, a = 1ll * a * a % M)
            if (k & 1) ans = 1ll * ans * a % M;
        return ans;
    }
    
    int main() {
        int n; scanf("%d", &n);
        printf("%lld", (222222224ll * n % M * n % M + 311111113ll * n + 177777779 + 288888891ll * Pow(n, M - 2)) % M);
    }```
    
    </details>
  • 相关阅读:
    Do the “StreamWriter.WriteLine()” function need to “lock()”?
    SQL Server Integration Services C#脚本任务示例 先看前二部分
    使用SSIS脚本任务触发事件,执行T-SQL命令并运行SMO 第二部分
    Getting started with the SSIS Script Task 第一部分
    对SQL Server的监控和报告
    在Visual Studio 2019中安装SQL Server Integration Services
    .Net ObjectContext.CreateQuery<T>(String, ObjectParameter[]) Method
    使用Redgate的SQL Monitor优化SQL Server资产监视
    将多行汇总为SQL Server数据的一行和一列
    用于SQL源的Power BI增量刷新
  • 原文地址:https://www.cnblogs.com/shawk/p/14392688.html
Copyright © 2011-2022 走看看