zoukankan      html  css  js  c++  java
  • #线段树、树状数组#D 筹备计划

    题目


    分析

    首先这个位置应该是带权中位数((geq frac{sum+1}{2}(奇数要加一,WA了几次了))),但是既然有这个选择的限制,
    那么要用线段树求出可选择的前驱和后继,然后用树状数组计算贡献,拆开计算就可以了


    代码

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define rr register
    using namespace std;
    typedef long long lll;
    const int N = 200011;
    lll a[N];
    int n, m, two[21], w[N << 2], lazy[N << 2];
    inline signed iut() {
        rr int ans = 0;
        rr char c = getchar();
        while (!isdigit(c)) c = getchar();
        while (isdigit(c)) ans = (ans << 3) + (ans << 1) + (c ^ 48), c = getchar();
        return ans;
    }
    inline void print(int ans) {
        if (ans > 9)
            print(ans / 10);
        putchar(ans % 10 + 48);
    }
    inline signed fan(int x) { return n - x + 1; }
    struct Tree_Array {
        lll c[N];
        inline void update(int x, lll y) {
            for (; x <= n; x += -x & x) c[x] += y;
        }
        inline lll query(int x) {
            rr lll ans = 0;
            for (; x; x -= -x & x) ans += c[x];
            return ans;
        }
    } CF[2], CR[2];
    inline void build(int k, int l, int r) {
        w[k] = r - l + 1, lazy[k] = -1;
        if (l == r)
            return;
        rr int mid = (l + r) >> 1;
        build(k << 1, l, mid);
        build(k << 1 | 1, mid + 1, r);
    }
    inline void pdown(int k, int l, int mid, int r) {
        w[k << 1] = lazy[k] * (mid - l + 1), w[k << 1 | 1] = lazy[k] * (r - mid);
        lazy[k << 1] = lazy[k << 1 | 1] = lazy[k], lazy[k] = -1;
    }
    inline void update(int k, int l, int r, int x, int y, int z) {
        if (l == x && r == y) {
            w[k] = z * (r - l + 1), lazy[k] = z;
            return;
        }
        rr int mid = (l + r) >> 1;
        if (~lazy[k])
            pdown(k, l, mid, r);
        if (y <= mid)
            update(k << 1, l, mid, x, y, z);
        else if (x > mid)
            update(k << 1 | 1, mid + 1, r, x, y, z);
        else
            update(k << 1, l, mid, x, mid, z), update(k << 1 | 1, mid + 1, r, mid + 1, y, z);
        w[k] = w[k << 1] + w[k << 1 | 1];
    }
    inline signed sum_pre(int k, int l, int r, int x, int y) {
        if (l == x && r == y)
            return w[k];
        rr int mid = (l + r) >> 1;
        if (~lazy[k])
            pdown(k, l, mid, r);
        if (y <= mid)
            return sum_pre(k << 1, l, mid, x, y);
        else if (x > mid)
            return sum_pre(k << 1 | 1, mid + 1, r, x, y);
        else
            return sum_pre(k << 1, l, mid, x, mid) + sum_pre(k << 1 | 1, mid + 1, r, mid + 1, y);
    }
    inline signed query(int k, int l, int r, int kth) {
        if (l == r)
            return l;
        rr int mid = (l + r) >> 1;
        if (~lazy[k])
            pdown(k, l, mid, r);
        if (kth <= w[k << 1])
            return query(k << 1, l, mid, kth);
        else
            return query(k << 1 | 1, mid + 1, r, kth - w[k << 1]);
    }
    inline lll calc(int now) {
        rr lll ans = 0;
        if (now > 1)
            ans += CF[1].query(now - 1) - CF[0].query(now - 1) * (n - now);
        if (now < n)
            ans += CR[1].query(fan(now + 1)) - CR[0].query(fan(now + 1)) * (now - 1);
        return ans;
    }
    signed main() {
        freopen("position.in", "r", stdin);
        freopen("position.out", "w", stdout);
        n = iut(), m = iut(), build(1, 1, n), two[0] = 1;
        for (rr int i = 1; i < 21; ++i) two[i] = two[i - 1] << 1;
        for (rr int i = 1; i <= n; ++i) a[i] = iut();
        for (rr int i = 1; i <= n; ++i) CF[0].c[i] = CF[0].c[i - 1] + a[i];
        for (rr int i = 1; i <= n; ++i) CF[1].c[i] = CF[1].c[i - 1] + a[i] * (n - i);
        for (rr int i = 1; i <= n; ++i) CR[0].c[i] = CR[0].c[i - 1] + a[n - i + 1];
        for (rr int i = 1; i <= n; ++i) CR[1].c[i] = CR[1].c[i - 1] + a[n - i + 1] * (n - i);
        for (rr int i = n; i; --i) CF[0].c[i] -= CF[0].c[i & (i - 1)];
        for (rr int i = n; i; --i) CF[1].c[i] -= CF[1].c[i & (i - 1)];
        for (rr int i = n; i; --i) CR[0].c[i] -= CR[0].c[i & (i - 1)];
        for (rr int i = n; i; --i) CR[1].c[i] -= CR[1].c[i & (i - 1)];
        for (rr int z, x, y; m; --m, putchar(10)) {
            z = iut(), x = iut(), y = iut();
            if (z == 1 || z == 2) {
                y = (z == 1) ? y : -y, a[x] += y;
                CF[0].update(x, y);
                CF[1].update(x, 1ll * y * (n - x));
                CR[0].update(fan(x), y);
                CR[1].update(fan(x), 1ll * y * (x - 1));
            } else
                update(1, 1, n, x, y, 4 - z);
            if (!w[1]) {
                printf("-1");
                continue;
            }
            rr lll t = (CF[0].query(n) + 1) >> 1, sum = 0, ans = 0;
            for (rr int I = 17; ~I; --I)
                if (ans + two[I] <= n && sum + CF[0].c[ans + two[I]] < t)
                    ans += two[I], sum += CF[0].c[ans];
            rr int t1 = -1, t2 = -1, s = sum_pre(1, 1, n, 1, ++ans);
            if (s > 0)
                t1 = query(1, 1, n, s);
            if (s < w[1])
                t2 = query(1, 1, n, s + 1);
            if (t1 == -1 || t2 == -1)
                t1 = ~t2 ? t2 : t1, t2 = ~t1 ? t1 : t2;
            print(calc(t1) <= calc(t2) ? t1 : t2);//注意输出编号小的
        }
        return 0;
    }
    
  • 相关阅读:
    矩阵
    手机APP和WAP版的区别
    学习的方法
    ASP.Net中jQuery控制div弹出框效果
    SQL SERVER字符串前加N转换为Unicode编码
    塞尔维亚国家简称编码
    VS2019项目模板中没有[ASP.NET空网站]的解决方案
    Scopus论文数据爬虫
    采集科研文献和数据,我告诉你一个能自动采集的黑科技
    CiteSpace入门教程
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13810231.html
Copyright © 2011-2022 走看看