Codeforces 1030F Putting Boxes Together 树状数组

Putting Boxes Together

二分找到分界点, 左边的往右移, 右边的往左移。

其实把a[ i ] - i 之后就变成了移到一个点, 然后我维护移到一个线段都要维护自闭了。

#include<bits/stdc++.h>
#define LL long long
#define LD long double
#define ull unsigned long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ALL(x) (x).begin(), (x).end()
#define fio ios::sync_with_stdio(false); cin.tie(0);

using namespace std;

const int N = 2e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);

template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}

int n, q, a[N], w[N];

struct Bit {
    LL a[N];
    void modify(int x, int v) {
        for(int i = x; i <= n; i += i & -i) a[i] += v;
    }
    LL sum(int x) {
        LL ans = 0;
        for(int i = x; i; i -= i & -i) ans += a[i];
        return ans;
    }
    LL query(int L, int R) {
        if(L > R) return 0;
        return sum(R) - sum(L - 1);
    }
} bit;

struct Bit2 {
    int a[N];
    void modify(int x, int v) {
        for(int i = x; i <= n; i += i & -i) add(a[i], v);
    }
    int sum(int x) {
        LL ans = 0;
        for(int i = x; i; i -= i & -i) add(ans, a[i]);
        return ans;
    }
    int query(int L, int R) {
        if(L > R) return 0;
        return (sum(R) - sum(L - 1) + mod) % mod;
    }
} prefix, suffix;

int main() {
    LL ret = 0;
    scanf("%d%d", &n, &q);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    for(int i = 1; i <= n; i++) scanf("%d", &w[i]);
    for(int i = 1; i <= n; i++) {
        bit.modify(i, w[i]);
        prefix.modify(i, 1LL * abs(a[i] - a[1] - i + 1) * w[i] % mod);
    }
    for(int i = n; i >= 1; i--)
        suffix.modify(i, 1LL * abs(a[n] - a[i] - n + i) * w[i] % mod);
    while(q--) {
        int x, y;
        scanf("%d%d", &x, &y);
        if(x < 0) {
            x = -x;
            bit.modify(x, -w[x]);
            prefix.modify(x, mod - (1LL * abs(a[x] - a[1] - x + 1) * w[x] % mod));
            suffix.modify(x, mod - (1LL * abs(a[n] - a[x] - n + x) * w[x] % mod));
            w[x] = y;
            bit.modify(x, w[x]);
            prefix.modify(x, 1LL * abs(a[x] - a[1] - x + 1) * w[x] % mod);
            suffix.modify(x, 1LL * abs(a[n] - a[x] - n + x) * w[x] % mod);
        } else {
            int len = y - x + 1;
            int low = a[x], high = a[y], p = low, low2, high2, p2, fen;
            while(low <= high) {
                int mid = low + high >> 1;
                low2 = x, high2 = y, p2 = y + 1;
                while(low2 <= high2) {
                    int mid2 = low2 + high2 >> 1;
                    if(a[mid2] > mid + mid2 - x) p2 = mid2, high2 = mid2 - 1;
                    else low2 = mid2 + 1;
                }
                LL valL = bit.query(x, p2 - 1);
                LL valR = bit.query(p2, y);
                if(valL > valR) p = mid, high = mid - 1, fen = p2;
                else low = mid + 1;
            }
            LL ans = 0;
            if(fen <= y) {
                add(ans, prefix.query(fen, y));
                sub(ans, bit.query(fen, y) % mod * (p - (a[1] + x - 1)) % mod);
            }
            if(fen - 1 >= x) {
                add(ans, suffix.query(x, fen - 1));
                sub(ans, bit.query(x, fen - 1) % mod * (a[n] - (n - x) - p) % mod);
            }
            printf("%lld\n", ans);
        }
    }
    return 0;
}

/*
*/

 

转载于:https://www.cnblogs.com/CJLHY/p/10865494.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值