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代码

原文地址:https://www.cnblogs.com/huyufeifei/p/11063646.html

时间: 2024-10-16 03:45:06

CF1030F 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 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

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

http://codeforces.com/blog/entry/62013 两个结论: 1.一定有一个箱子不用动. 2.不动的箱子一定是加权前缀和为S/2的那个. 1显然,2由1易得. 于是问题变为:求一段区间前缀和>S/2的第一个数的位置.显然先求出S/2,再线段树上二分即可,实现过程见代码. 自定义struct比stl:pair快,注意取模和爆long long的问题. 1 #include<cstdio> 2 #include<algorithm> 3 #define

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

#include <iostream> #include <algorithm> #include <cstdio> #include <math.h> #include <set> #include <map> #include <queue> #include <string> #include <string.h> #include <bitset> #define REP(i,a

中位数及带权中位数题集

codevs 3625 1 #include <bits/stdc++.h> 2 using namespace std; 3 int x[11111], y[11111]; 4 int main() 5 { 6 int n; scanf("%d", &n); 7 for(int i = 1; i <= n; i++) scanf("%d %d", &x[i], &y[i]); 8 ///先处理y 9 sort(y + 1,

uva 12657 - Boxes in a Line(AC和TLE的区别,为什么说STL慢..)

用STL中的list写的,TLE #include<cstdio> #include<iostream> #include<cstring> #include<list> #include<algorithm> using namespace std; list<int> l; list<int>::iterator it1,it2,it3,it4,it5,it; void work(int a,int a1=1,int

[LeetCode] Remove Boxes 移除盒子

Given several boxes with different colors represented by different positive numbers. You may experience several rounds to remove boxes until there is no box left. Each time you can choose some continuous boxes with the same color (composed of k boxes

UVa 12657 Boxes in a Line(应用双链表)

Boxes in a Line You have n boxes in a line on the table numbered 1 . . . n from left to right. Your task is to simulate 4 kinds of commands: ? 1 X Y : move box X to the left to Y (ignore this if X is already the left of Y ) ? 2 X Y : move box X to th

UVa - 103 - Stacking Boxes

Background Some concepts in Mathematics and Computer Science are simple in one or two dimensions but become more complex when extended to arbitrary dimensions. Consider solving differential equations in several dimensions and analyzing the topology o