CF1030F Putting Boxes Together

Posted huyufeifei

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1030F Putting Boxes Together相关的知识,希望对你有一定的参考价值。

CF1030F - Putting Boxes Together

题意:给定数轴上的n个物体,你要把第l个物体到第r个物体之间的所有物体挪到挨在一起,使得总消耗最小。带修。消耗是重量乘距离。

解:就是带权中位数。有个结论是一定有一个物体不动。还有一个结论是不动的物体左右两边权值和之差最小。

于是我们先找到那个不动位置,然后计算把别的挪过去的消耗。

找它就先查权值和,先+1然后除以2,然后找到那个位置。

计算消耗就维护一个全挪到最左最右的消耗,一个从最左最右散开的消耗,然后跟sum加加减减一下。不需要在线段树上维护很多东西。

技术图片
  1 /** CF 1030F */
  2 #include <bits/stdc++.h>
  3 
  4 typedef long long LL;
  5 
  6 const int N = 200010, MO = 1e9 + 7;
  7 
  8 LL sum[N << 2], tr[N << 2], tl[N << 2], w[N];
  9 int X[N], xx, a[N], n;
 10 
 11 inline void Add(int &a, const int &b) 
 12     a += b;
 13     if(a >= MO) a -= MO;
 14     if(a < 0) a += MO;
 15     return;
 16 
 17 
 18 struct TA 
 19     int ta[N];
 20     inline void add(int i, int v) 
 21         for(; i <= n; i += i & (-i)) 
 22             Add(ta[i], v);
 23         
 24         return;
 25     
 26     inline int ask(int i) 
 27         int ans = 0;
 28         for(; i; i -= i & (-i)) 
 29             Add(ans, ta[i]);
 30         
 31         return ans;
 32     
 33     inline int getSum(int l, int r) 
 34         return (ask(r) - ask(l - 1) + MO) % MO;
 35     
 36 ta1, ta2, ta3, ta4;
 37 
 38 inline void pushup(int l, int r, int o) 
 39     int ls = o << 1, rs = ls | 1, mid = (l + r) >> 1;
 40     sum[o] = sum[ls] + sum[rs];
 41     tl[o] = tl[ls] + tl[rs] + sum[rs] * (X[mid + 1] - X[l] - (mid - l + 1));
 42     tr[o] = tr[ls] + tr[rs] + sum[ls] * (X[r] - X[mid] - (r - mid));
 43     return;
 44 
 45 
 46 void build(int l, int r, int o) 
 47     if(l == r) 
 48         sum[o] = w[r];
 49         return;
 50     
 51     int mid = (l + r) >> 1;
 52     build(l, mid, o << 1);
 53     build(mid + 1, r, o << 1 | 1);
 54     pushup(l, r, o);
 55     return;
 56 
 57 
 58 void change(int p, int v, int l, int r, int o) 
 59     if(l == r) 
 60         sum[o] = v;
 61         return;
 62     
 63     int mid = (l + r) >> 1;
 64     if(p <= mid) 
 65         change(p, v, l, mid, o << 1);
 66     
 67     else 
 68         change(p, v, mid + 1, r, o << 1 | 1);
 69     
 70     pushup(l, r, o);
 71     return;
 72 
 73 
 74 LL getSum(int L, int R, int l, int r, int o) 
 75     if(L <= l && r <= R) 
 76         return sum[o];
 77     
 78     int mid = (l + r) >> 1;
 79     LL ans = 0;
 80     if(L <= mid) 
 81         ans = getSum(L, R, l, mid, o << 1);
 82     
 83     if(mid < R) 
 84         ans += getSum(L, R, mid + 1, r, o << 1 | 1);
 85     
 86     return ans;
 87 
 88 
 89 int getPos(LL k, int l, int r ,int o) 
 90     if(l == r) 
 91         return r;
 92     
 93     int mid = (l + r) >> 1;
 94     if(k <= sum[o << 1]) 
 95         return getPos(k, l, mid, o << 1);
 96     
 97     else 
 98         return getPos(k - sum[o << 1], mid + 1, r, o << 1 | 1);
 99     
100 
101 
102 int Ask(int x, int y) 
103     LL sum = getSum(x, y, 1, n, 1);
104     LL sum2 = 0;
105     if(x > 1) sum2 = getSum(1, x - 1, 1, n, 1);
106     LL delta = sum2 + ((sum + 1) >> 1);
107     int p = getPos(delta, 1, n, 1);
108     int ans = 0;
109     if(x < p) 
110         LL Sum = getSum(x, p - 1, 1, n, 1) % MO;
111         Add(ans, ((LL)ta3.getSum(x, p - 1) - ta4.getSum(x, p - 1) - Sum * (X[n] - X[p] - (n - p)) % MO) % MO);
112     
113     if(p < y) 
114         LL Sum = getSum(p + 1, y, 1, n, 1) % MO;
115         Add(ans, ((LL)ta1.getSum(p + 1, y) - ta2.getSum(p + 1, y) - Sum * (X[p] - X[1] - (p - 1))) % MO);
116         //printf("%d %d %lld * %d\n", ta1.getSum(p + 1, y), ta2.getSum(p + 1, y), Sum, (X[p] - X[1] - (p - 1)));
117     
118     return ans;
119 
120 
121 int main() 
122     
123     int q;
124     scanf("%d%d", &n, &q);
125     for(int i = 1; i <= n; i++) 
126         scanf("%d", &X[i]);
127     
128     for(int i = 1; i <= n; i++) 
129         scanf("%lld", &w[i]);
130     
131     build(1, n, 1);
132     for(int i = 1; i <= n; i++) 
133         LL c = w[i];
134         ta1.add(i, c * (X[i] - X[1]) % MO);
135         ta2.add(i, c * (i - 1) % MO);
136         ta3.add(i, c * (X[n] - X[i]) % MO);
137         ta4.add(i, c * (n - i) % MO);
138     
139 
140     int x, y;
141     for(int i = 1; i <= q; i++) 
142         scanf("%d%d", &x, &y);
143         if(x < 0) 
144             x = -x;
145             change(x, y, 1, n, 1);
146             int dt = (y - w[x] + MO) % MO;
147             ta1.add(x, (LL)dt * (X[x] - X[1]) % MO);
148             ta2.add(x, (LL)dt * (x - 1) % MO);
149             ta3.add(x, (LL)dt * (X[n] - X[x]) % MO);
150             ta4.add(x, (LL)dt * (n - x) % MO);
151             w[x] = y;
152         
153         else 
154             int ans = Ask(x, y);
155             printf("%d\n", ans);
156         
157     
158 
159     return 0;
160 
AC代码

 

以上是关于CF1030F Putting Boxes Together的主要内容,如果未能解决你的问题,请参考以下文章

Putting Boxes Together CodeForces - 1030F (带权中位数)

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

[CFR512 div 2 F]Putting Boxes Together(线段树)

CF821C Okabe and Boxes

CF1066D Boxes Packing

CF1066D Boxes Packing(二分答案)