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 stands in the cell aiai and has weight wiwi. All aiai are distinct, moreover, ai?1<aiai?1<ai holds for all valid ii.

You would like to put together some boxes. Putting together boxes with indices in the segment [l,r][l,r] means that you will move some of them in such a way that their positions will form some segment [x,x+(r?l)][x,x+(r?l)].

In one step you can move any box to a neighboring cell if it isn‘t occupied by another box (i.e. you can choose ii and change aiai by 11, all positions should remain distinct). You spend wiwi units of energy moving the box ii by one cell. You can move any box any number of times, in arbitrary order.

Sometimes weights of some boxes change, so you have queries of two types:

  1. idid nwnw — weight widwid of the box idid becomes nwnw.
  2. ll rr — you should compute the minimum total energy needed to put together boxes with indices in [l,r][l,r]. Since the answer can be rather big, print the remainder it gives when divided by 1000000007=109+71000000007=109+7. Note that the boxes are not moved during the query, you only should compute the answer.

Note that you should minimize the answer, not its remainder modulo 109+7109+7. So if you have two possible answers 2?109+132?109+13and 2?109+142?109+14, you should choose the first one and print 109+6109+6, even though the remainder of the second answer is 00.

Input

The first line contains two integers nn and qq (1≤n,q≤2?1051≤n,q≤2?105) — the number of boxes and the number of queries.

The second line contains nn integers a1,a2,…ana1,a2,…an (1≤ai≤1091≤ai≤109) — the positions of the boxes. All aiai are distinct, ai?1<aiai?1<ai holds for all valid ii.

The third line contains nn integers w1,w2,…wnw1,w2,…wn (1≤wi≤1091≤wi≤109) — the initial weights of the boxes.

Next qq lines describe queries, one query per line.

Each query is described in a single line, containing two integers xx and yy. If x<0x<0, then this query is of the first type, where id=?xid=?x, nw=ynw=y (1≤id≤n1≤id≤n, 1≤nw≤1091≤nw≤109). If x>0x>0, then the query is of the second type, where l=xl=x and r=yr=y (1≤lj≤rj≤n1≤lj≤rj≤n). xx can not be equal to 00.

Output

For each query of the second type print the answer on a separate line. Since answer can be large, print the remainder it gives when divided by 1000000007=109+71000000007=109+7.

Example

input

Copy

5 81 2 6 7 101 1 1 1 21 11 51 33 5-3 5-1 101 42 5

output

Copy

01034187

Note

Let‘s go through queries of the example:

  1. 1 11 1 — there is only one box so we don‘t need to move anything.
  2. 1 51 5 — we can move boxes to segment [4,8][4,8]: 1?|1?4|+1?|2?5|+1?|6?6|+1?|7?7|+2?|10?8|=101?|1?4|+1?|2?5|+1?|6?6|+1?|7?7|+2?|10?8|=10.
  3. 1 31 3 — we can move boxes to segment [1,3][1,3].
  4. 3 53 5 — we can move boxes to segment [7,9][7,9].
  5. ?3 5?3 5 — w3w3 is changed from 11 to 55.
  6. ?1 10?1 10 — w1w1 is changed from 11 to 1010. The weights are now equal to w=[10,1,5,1,2]w=[10,1,5,1,2].
  7. 1 41 4 — we can move boxes to segment [1,4][1,4].
  8. 2 52 5 — we can move boxes to segment [5,8][5,8].

思路:

树状数组加二分

  1 #include <iostream>
  2 #include <fstream>
  3 #include <sstream>
  4 #include <cstdlib>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <string>
  8 #include <cstring>
  9 #include <algorithm>
 10 #include <queue>
 11 #include <stack>
 12 #include <vector>
 13 #include <set>
 14 #include <map>
 15 #include <list>
 16 #include <iomanip>
 17 #include <cctype>
 18 #include <cassert>
 19 #include <bitset>
 20 #include <ctime>
 21
 22 using namespace std;
 23
 24 #define pau system("pause")
 25 #define ll long long
 26 #define pii pair<int, int>
 27 #define pb push_back
 28 #define pli pair<ll, int>
 29 #define pil pair<int, ll>
 30 #define clr(a, x) memset(a, x, sizeof(a))
 31
 32 const double pi = acos(-1.0);
 33 const int INF = 0x3f3f3f3f;
 34 const int MOD = 1e9 + 7;
 35 const double EPS = 1e-9;
 36
 37 /*
 38 #include <ext/pb_ds/assoc_container.hpp>
 39 #include <ext/pb_ds/tree_policy.hpp>
 40 using namespace __gnu_pbds;
 41 #define TREE tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update>
 42 TREE T;
 43 */
 44
 45 int n, q;
 46 ll a[200015], w[200015];
 47 ll c1[200015], c2[200015];
 48 inline int lb(int x) {return x & -x;}
 49 void add1(int p, ll x) {
 50     for (; p <= n; p += lb(p)) c1[p] += x;
 51 }
 52 ll query1(int p) {
 53     ll res = 0;
 54     for (; p; p -= lb(p)) res += c1[p];
 55     return res;
 56 }
 57 void add2(int p, ll x) {
 58     for (; p <= n; p += lb(p)) {
 59         c2[p] += x;
 60         if (c2[p] >= MOD) c2[p] -= MOD;
 61     }
 62 }
 63 ll query2(int p) {
 64     ll res = 0;
 65     for (; p; p -= lb(p)) res += c2[p];
 66     return res % MOD;
 67 }
 68 int get_p(int l, int r) {
 69     ll r1 = query1(l - 1);
 70     ll r2 = query1(r) - r1;
 71     int mi, res = l;
 72     while (l <= r) {
 73         mi = l + r >> 1;
 74         if ((query1(mi) - r1) * 2 >= r2) {
 75             r = (res = mi) - 1;
 76         } else {
 77             l = mi + 1;
 78         }
 79     }
 80     return res;
 81 }
 82 ll cal(int l, int r, int p) {
 83     ll res1 = query2(r) - query2(p - 1) - (query1(r) - query1(p - 1)) % MOD * a[p];
 84     ll res2 = (query1(p) - query1(l - 1)) % MOD * a[p] - (query2(p) - query2(l - 1));
 85     return ((res1 + res2) % MOD + MOD) % MOD;
 86 }
 87 int main() {
 88     scanf("%d%d", &n, &q);
 89     for (int i = 1; i <= n; ++i) {
 90         scanf("%lld", &a[i]);
 91         a[i] -= i;
 92     }
 93     for (int i = 1; i <= n; ++i) {
 94         scanf("%lld", &w[i]);
 95     }
 96     for (int i = 1; i <= n; ++i) {
 97         add1(i, w[i]);
 98         add2(i, w[i] * a[i] % MOD);
 99     }
100     while (q--) {
101         int l, r;
102         scanf("%d%d", &l, &r);
103         if (l < 0) {
104             add1(-l, r - w[-l]);
105             add2(-l, (r - w[-l]) * a[-l] % MOD);
106             w[-l] = r;
107         } else {
108             int p = get_p(l, r);
109             printf("%lld\n", cal(l, r, p));
110         }
111     }
112     return 0;
113 }

原文地址:https://www.cnblogs.com/BIGTOM/p/9738058.html

时间: 2024-08-10 07:38:37

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

2018中国大学生程序设计竞赛 - 网络选拔赛 1010 YJJ&#39;s Salesman 【离散化+树状数组维护区间最大值】

题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6447 YJJ's Salesman Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 919    Accepted Submission(s): 290 Problem Description YJJ is a salesman who h

Playrix Codescapes Cup (Codeforces Round #413, rated, Div. 1 + Div. 2) C. Fountains 【树状数组维护区间最大值】

题目传送门:http://codeforces.com/contest/799/problem/C C. Fountains time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Arkady plays Gardenscapes a lot. Arkady wants to build two new fountains. The

CF Educational Codeforces Round 10 D. Nested Segments 离散化+树状数组

题目链接:http://codeforces.com/problemset/problem/652/D 大意:给若干个线段,保证线段端点不重合,问每个线段内部包含了多少个线段. 方法是对所有线段的端点值离散化,按照左端点从大到小排序,顺着这个顺序处理所有线段,那么满足在它内部的线段一定是之前已经扫到过的.用树状数组判断有多少是在右端点范围内. 1 #include <iostream> 2 #include <vector> 3 #include <algorithm>

Codeforces Round #425 (Div. 2) D 树链剖分 + 树状数组维护区间

一看就知道 可以LCA判断做 也可以树链剖分拿头暴力 然而快速读入和线段树维护区间会T70 于是只能LCA? 线段树的常数不小 于是需要另外一种办法来进行区间加减和查询区间和 就是使用树状数组 这个题的代码 #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<vector> #include<cstring> using na

【Hihocoder 1167】 高等理论计算机科学 (树链的交,线段树或树状数组维护区间和)

[题意] 时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 少女幽香这几天正在学习高等理论计算机科学,然而她什么也没有学会,非常痛苦.所以她出去晃了一晃,做起了一些没什么意义的事情来放松自己.门前有一颗n个节点树,幽香发现这个树上有n个小精灵.然而这些小精灵都比较害羞,只会在一条特定的路径上活动.第i个小精灵会在ai到bi的路径上活动.两个小精灵是朋友,当且仅当它们的路径是有公共点的.于是幽香想要知道,有多少对小精灵a和b,a和b是朋友呢?其中a不等于b,a,b和b,

hdu 5654 xiaoxin and his watermelon candy 树状数组维护区间唯一元组

题目链接 题意:序列长度为n(1<= n <= 200,000)的序列,有Q(<=200,000)次区间查询,问区间[l,r]中有多少个不同的连续递增的三元组. 思路:连续三元组->递推O(n)将第一次出现该三元组的下标记录到树状数组中,并且用一个Next[]来表示递推关系,即同一个三元组下一次出现的位置是Next[x];这很关键,在之后按照左边界处理时(有点像莫队算法),一直递推在l+1左侧重复出现的三元组,为了把该三元组推到出现在[l,r]或者[r+1,..]中,这样不重不漏.

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

树状数组维护区间最值

在区间求和时,我们只需求出 [1, r],[1,l?1],利用前缀和的可减性,得到区间 [l,r] 的和. 但区间最值不满足这个性质. 我们可以把区间 [l,r] 拆分成若干个子区间,再合并得到答案. 画图可知,max_i需要的 max 只有 max_{i-2^0}, max_{i-2^1}, max_{i-2^2} ... max_{i-lowbit(i)+1}. 修改 void change(int r) { c[r] = a[r]; for(int i = 1; i < lowbit(r)

Codeforces Round #629 (Div. 3) F - Make k Equal (离散化 树状数组维护前缀和)

https://codeforces.com/contest/1328/problem/F 首先把a数组处理成pair对(num,cnt),表示数字num有cnt个,然后按num升序排序离散化一下. 对于一个数x,若想使得小于x的数字都变成x,必须先把所有小于x的数变成x-1,然后再+1变成x. 同理,要使得大于x的数变成x,必须把所有大于x的数字变成x+1,然后再-1变成x. 以上是题意所要求的必须操作. 思路: 1. 用f[i]数组记录离散化后前i大的数字的总数,那么对于任意第i大数字,可以