CodeForces 1058 F Putting Boxes Together 树状数组,带权中位数

Putting Boxes Together

题意:

现在有n个物品,第i个物品他的位置在a[i],他的重量为w[i]。每一个物品移动一步的代价为他的w[i]。目前有2种操作:

1. x y 将第x的物品的重量改为y

2.l r 将编号在 [ l, r ]之间的所有物品移动到一起,求最小的花费是多少。

 

如果移动一个物品移动一步的代价是1的话,对于[1,n]来说,那么中间位置就是 a[(1+n)/2]. 也就是最中间的那个物品的位置。

现在移动一步他的代价是w[i],那么中间位置就是 sum(1,k) >= sum(k+1,n) 在满足前面的条件下,k最小。

我们可以用2分跑出最小的k,这样我们就确定了位置。

接来下我们的问题就是如何移动物品了。

我们可以把所有的物品移动到区间[1,n]上,记录下花费。

然后在把这一整段的物品整体移动到对应区间就好了。

注意的就是对于中间点来说,整体区间移动的正负是不一样的。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
 4 #define LL long long
 5 #define ULL unsigned LL
 6 #define fi first
 7 #define se second
 8 #define pb push_back
 9 #define lson l,m,rt<<1
10 #define rson m+1,r,rt<<1|1
11 #define lch(x) tr[x].son[0]
12 #define rch(x) tr[x].son[1]
13 #define max3(a,b,c) max(a,max(b,c))
14 #define min3(a,b,c) min(a,min(b,c))
15 typedef pair<int,int> pll;
16 const int inf = 0x3f3f3f3f;
17 const LL INF = 0x3f3f3f3f3f3f3f3f;
18 const LL mod =  (int)1e9+7;
19 const int N = 2e5 + 100;
20 LL tree1[N], tree2[N];
21 int n, q;
22 int a[N], w[N];
23 inline int lowbit(int x){
24     return x & (-x);
25 }
26 void add1(int x, LL v){
27     for(int i = x; i <= n; i+=lowbit(i))
28         tree1[i] += v;
29 }
30 void add2(int x, LL v){
31     for(int i = x; i <= n; i+=lowbit(i))
32         tree2[i] += v;
33 }
34 LL query1(int x){
35     LL ret = 0;
36     for(int i = x; i; i -= lowbit(i))
37         ret += tree1[i];
38     return ret;
39 }
40 LL query2(int x){
41     LL ret = 0;
42     for(int i = x; i; i -= lowbit(i))
43         ret += tree2[i];
44     return ret % mod;
45 }
46 LL sum1(int l, int r){
47     if(l > r) return 0;
48     return query1(r) - query1(l-1);
49 }
50 LL sum2(int l, int r){
51     if(l > r) return 0;
52     return query2(r) - query2(l-1);
53 }
54 int GG(int l, int r){
55     if(l == r) return 0;
56     int ll = l, rr = r, mm;
57     LL tot = sum1(l, r), t1 , t2;
58     while(ll <= rr){
59         mm = ll + rr >> 1;
60         t1 = sum1(l, mm);
61         t2 = tot - t1;
62         if(t1 < t2) ll = mm + 1;
63         else rr = mm - 1;
64     }
65     LL ret = 0;
66     ret -= sum2(l,ll-1);
67     ret += ((sum1(l,ll-1)%mod) * (a[ll]-1-(ll-1)))%mod;
68     ret += sum2(ll+1,r);
69     ret -= ((sum1(ll+1,r)%mod) * (a[ll]+1 -(ll+1)))%mod;
70     return (ret%mod + mod) % mod;
71 }
72 int main(){
73     scanf("%d%d", &n, &q);
74     for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
75     for(int i = 1; i <= n; i++){
76         scanf("%d", &w[i]);
77         add1(i, w[i]);
78         LL v = ((1ll*a[i]-i)*w[i])%mod;
79         add2(i, v);
80     }
81     int l, r;
82     for(int i = 1; i <= q; i++){
83         scanf("%d%d", &l, &r);
84         if(l < 0){
85             l = -l;
86             add1(l, r-w[l]);
87             LL v = (((1ll*a[l]-l)*r)%mod)-((1ll*a[l]-l)*w[l])%mod;
88             add2(l, v);
89             w[l] = r;
90         }
91         else printf("%d\n", GG(l,r));
92     }
93     return 0;
94 }
View Code

 

posted @ 2018-09-28 14:37  Schenker  阅读(346)  评论(0编辑  收藏  举报