• 自嗨测试赛3


    A 任意模数快速插值

    题目大意 : 求每个区间最大值与最小值乘积的和

    • 线段树,每个叶子节点维护当前节点到i的最大值,最小值。发现最大值是不增,最小值是不降,所以区间覆盖一部分,实现的有点复杂

    • 还可以分治求,代码短

    Code

    Show Code
    #include <cstdio>
    #include <algorithm>
    #define ls (rt << 1)
    #define rs (rt << 1| 1)
    #define Add(x, y) ({int xx = x + y; xx < M ? xx : xx - M; })
    
    using namespace std;
    const int N = 5e5 + 5, M = 998244353;
    
    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, ans;
    
    struct Tree {
        int s, d1, x1, d2, x2, s1, s2, t1, t2;
    }t[N*4];
    
    void Update1(int rt, int l, int r, int w) {
        t[rt].d1 = t[rt].x1 = t[rt].t1 = w; 
        t[rt].s1 = 1ll * w * (r - l + 1) % M;
        t[rt].s = 1ll * w * t[rt].s2 % M;
    }
    
    void Update2(int rt, int l, int r, int w) {
        t[rt].d2 = t[rt].x2 = t[rt].t2 = w; 
        t[rt].s2 = 1ll * w * (r - l + 1) % M;
        t[rt].s = 1ll * w * t[rt].s1 % M;
    }
    
    void Pushdown(int rt, int l, int r) {
        int mid = l + r >> 1;
        if (t[rt].t1 != -1) {
            Update1(ls, l, mid, t[rt].t1);
            Update1(rs, mid+1, r, t[rt].t1);
        }
        if (t[rt].t2 != -1) {
            Update2(ls, l, mid, t[rt].t2);
            Update2(rs, mid+1, r, t[rt].t2);
        }
        t[rt].t1 = t[rt].t2 = -1;
    }
    
    void Modify1(int rt, int l, int r, int x, int y, int w) {
        if (t[rt].x1 >= w) return;
        if (x <= l && r <= y && t[rt].d1 < w) return Update1(rt, l, r, w);
        int mid = l + r >> 1; Pushdown(rt, l, r);
        if (x <= mid) Modify1(ls, l, mid, x, y, w);
        if (y >  mid) Modify1(rs, mid+1, r, x, y, w);
        t[rt].d1 = max(t[ls].d1, t[rs].d1);
        t[rt].x1 = min(t[ls].x1, t[rs].x1);
        t[rt].s1 = Add(t[ls].s1, t[rs].s1);
        t[rt].s = Add(t[ls].s, t[rs].s);
    }
    
    void Modify2(int rt, int l, int r, int x, int y, int w) {
        if (t[rt].d2 <= w) return;
        if (x <= l && r <= y && t[rt].x2 > w) return Update2(rt, l, r, w);
        int mid = l + r >> 1; Pushdown(rt, l, r);
        if (x <= mid) Modify2(ls, l, mid, x, y, w);
        if (y >  mid) Modify2(rs, mid+1, r, x, y, w);
        t[rt].d2 = max(t[ls].d2, t[rs].d2);
        t[rt].x2 = min(t[ls].x2, t[rs].x2);
        t[rt].s2 = Add(t[ls].s2, t[rs].s2);
        t[rt].s = Add(t[ls].s, t[rs].s);
    }
    
    int Ask(int rt, int l, int r, int x, int y) {
        if (x <= l && r <= y) return t[rt].s;
        int mid = l + r >> 1, ans = 0; Pushdown(rt, l, r);
        if (x <= mid) ans = Ask(ls, l, mid, x, y);
        if (y > mid) ans = Add(ans, Ask(rs, mid + 1, r, x, y));
        return ans;
    }
    
    int main() {
        freopen("chazhi.in", "r", stdin);
        freopen("chazhi.out", "w", stdout);
        n = read();
        for (int i = n * 4; i >= 1; --i) 
            t[i].d2 = t[i].x2 = 1e9, t[i].t1 = t[i].t2 = -1;
        for (int i = 1; i <= n; ++i) {
            int x = read();
            Modify1(1, 1, n, 1, i, x);
            Modify2(1, 1, n, 1, i, x);
            if ((ans += Ask(1, 1, n, 1, i)) >= M) ans -= M;
        }
        printf("%d
    ", ans);
        return 0;
    }
    

    B 斗转星移

    题目大意 : 坐标系上n个点,每次可以绕原点旋转或绕一直线对称,问一些点经过前几个操作后的坐标

    • 真的挺简单,就记录一下怎么变就行

    Code

    Show Code
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    typedef long long ll;
    const int N = 1e6 + 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, x[N], y[N], z[N];
    
    struct Node {
        int a, b; ll c;
        ll Cal(int i) {
            return a * x[i] + b * y[i] + c;
        }
    }a[N], b[N];
    
    Node Change(Node x) {
        return (Node) {-x.a, -x.b, -x.c};
    }
    
    int main() {
        freopen("passing.in", "r", stdin);
        freopen("passing.out", "w", stdout);
        n = read();
        for (int i = 1; i <= n; ++i)
            x[i] = read(), y[i] = read();
        a[0].a = b[0].b = 1;
        m = read();
        for (int i = 1; i <= m; ++i) {
            int op = read();
            a[i] = a[i-1], b[i] = b[i-1];
            if (op == 1) a[i] = Change(a[i]), swap(a[i], b[i]);
            else if (op == 2) b[i] = Change(b[i]), swap(a[i], b[i]);
            else if (op == 3) a[i] = Change(a[i]), a[i].c += read() * 2;
            else if (op == 4) b[i] = Change(b[i]), b[i].c += read() * 2;
        }
        for (int q = read(); q; q--) {
            int x1 = read(), x2 = read();
            printf("%lld %lld
    ", a[x1].Cal(x2), b[x1].Cal(x2));
        }
        return 0;
    }
    

    C 如何更快出题 (Unaccepted)

    题目大意 :

    Code

    Show Code
  • 相关阅读:
    HDU 5716 带可选字符的多字符串匹配(ShiftAnd)
    挑战程序设计竞赛 2.2 一往直前!贪心法
    再叩首
    2016 Multi-University Training Contest 1 总结
    2016 Multi-University Training Contest 2 总结
    2016 Multi-University Training Contest 3 总结
    2016 Multi-University Training Contest 4 总结
    2016 Multi-University Training Contest 5&6 总结
    2016 Multi-University Training Contest 7 总结
    2016 Multi-University Training Contest 8 总结
  • 原文地址:https://www.cnblogs.com/shawk/p/14507504.html
Copyright © 2020-2023  润新知