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
", 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
", ans);
156         }
157     }
158 
159     return 0;
160 }
AC代码
原文地址:https://www.cnblogs.com/huyufeifei/p/11063646.html