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

时间: 2024-10-14 07:59:43

Codeforces 1030F Putting Boxes Together 树状数组的相关文章

codeforces round 512 F. Putting Boxes Together 树状数组维护区间加权平均数

F. Putting Boxes Together time limit per test 2.5 seconds memory limit per test 256 megabytes input standard input output standard output There is an infinite line consisting of cells. There are nn boxes in some cells of this line. The ii-th box stan

Codeforces 216D Spider&#39;s Web 树状数组+模拟

题目链接:http://codeforces.com/problemset/problem/216/D 题意: 对于一个梯形区域,如果梯形左边的点数!=梯形右边的点数,那么这个梯形为红色,否则为绿色, 问: 给定的蜘蛛网中有多少个红色. 2个树状数组维护2个线段.然后暴力模拟一下,因为点数很多但需要用到的线段树只有3条,所以类似滚动数组的思想优化内存. #include<stdio.h> #include<iostream> #include<string.h> #in

codeforces 570 D. Tree Requests 树状数组+dfs搜索序

链接:http://codeforces.com/problemset/problem/570/D D. Tree Requests time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Roman planted a tree consisting of n vertices. Each vertex contains a low

Codeforces 635D Factory Repairs【树状数组】

又是看了很久的题目... 题目链接: http://codeforces.com/contest/635/problem/D 题意: 一家工厂生产维修之前每天生产b个,维修了k天之后每天生产a个,维修期间不生产. 若干操作: 1. 1 d aa 第d天要求aa个订单,一个订单对应一个物品,必须在这一天中完成. 2. 2 d 第d天开始维修,最终能得到多少订单. 分析: 树状数组分别维护维修前和维修后得到的订单数,这样对于不同的维修日期,把这两种相加即可. 代码: #include<cstdio>

codeforces 597C C. Subsequences(dp+树状数组)

题目链接: C. Subsequences time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output For the given sequence with n different elements find the number of increasing subsequences with k + 1 elements. It is

CodeForces 540E - Infinite Inversions(离散化+树状数组)

花了近5个小时,改的乱七八糟,终于A了. 一个无限数列,1,2,3,4,...,n....,给n个数对<i,j>把数列的i,j两个元素做交换.求交换后数列的逆序对数. 很容易想到离散化+树状数组,但是发现那些没有交换的数也会产生逆序对数,但我没有算. 经明神提示, 把没有用到的数字段化成点.然后用树状数组算一下就好了. 然后我用一个数组记录每个点的长度.比如 <1,2><5,6>,1,2,3,4,5,6只有1,2,5,6用到了,那么离散化为1,2,3,4,5,f[1]=

Codeforces 486E LIS of Sequence --树状数组

题意: 一个序列可能有多个最长子序列,现在问每个元素是以下三个种类的哪一类: 1.不属于任何一个最长子序列 2.属于其中某些但不是全部最长子序列 3.属于全部最长子序列 解法: 我们先求出dp1[i]表示1~i 的最长递增子序列长度, dp2[i]表示 n~i 的最长递减子序列长度(严格增减),这里我们可以用维护最大值的树状数组来解决,开始还以为要用nlogn求LIS的那种算法,当然那样应该也可以,这里元素值是1~10^5的,可以直接用树状数组,如果元素值任意的话,我们离散化一下也可以用树状数组

codeforces 652D Nested Segments 离散化+树状数组

题意:给你若干个区间,询问每个区间包含几个其它区间 分析:区间范围比较大,然后离散化,按右端点排序,每次更新树状数组中的区间左端点,查询区间和 注:(都是套路) #include<cstdio> #include<cstring> #include<queue> #include<cstdlib> #include<algorithm> #include<vector> #include<cmath> using name

Codeforces 383C . Propagating tree【树状数组,dfs】

题目大意: 有一棵树,对这个树有两种操作:1:表示为(1 x val),在编号为x的节点上加上val,然后给x节点的每个儿子加上- val,再给每个儿子的儿子加上-(- val),一直加到没有儿子为止.2:表示为(2 x)查询x节点上的值. 做法: 由于每次修改操作修改的并不是一个值,而是很多值,那我们将该题抽象成区间修改,点查询的问题.那怎么抽象呢?可以明白的是,每次操作虽然有加有减,但是每次做加法操作,或者减法操作的都是同一部分数(也就是说,在某次加上同一个数的节点们,下次操作一定是加上或者