昨晚的比赛题。(像我这种蒟蒻只能打打div2)

题意

  给你$n$个物品,每一个物品$i$,有一个权值$w_i$和一个位置$a_i$,定义移动一个物品$i$到位置$t$的代价为$w_i * \left |a_i - t  \right |$,要求你写一个数据结构支持以下两种操作:

    1、修改一个物品的权值

    2、查询把一个区间内全部移到相邻的位置的最小值。

  举个栗子:如果要把$[l, r]$移到相邻的位置,就是对于$\forall i \in [l, r]$,要有$pos_i = x + i - l\ (1 \leq x \leq n - (r - l))$,然后要确定这个$x$使移动的总代价最小,最后要求这个最小的代价对$1e9 + 7$取模的结果,每次询问独立。

  注意:要先使总代价最小然后再取模,而不是取模后最小。

  保证给出的$a_i$递增。

两个原题:

  一个简单题:

    我们有很经典的货仓选址的模型,就是在直线上有$n$个点,每一个点$i$有一个位置$pos_i$,每一个点有一个货物。定义运输货物的代价是移动的距离。现在要在直线上选择一个点建立货仓,要把所有的货物都运到这个点,要求使使代价最小,求这个最小代价。

    很简单吧,中位数。

    抄一段lyd书上的证明:先把所有的点按照$pos_i$排序,假设货仓建在$X$,左侧的点有$P$个,右侧的点有$Q$个。如果$P < Q$,那么把$X$往右移动会使答案变优,同理当$P > Q$使把$X$向左移动会使答案变优,所有最优解会在$P == Q$的地方产生。

    再抄一句:当$n$是偶数的时候,这时$pos_{\frac{n}{2}}$和$pos_{\frac{n + 1}{2}}$中的点都可以是最优解。

  稍微强化板:

    现在每一个货仓$i$里有$w_i$个货物。

    排序后,找到第一个$X$,使$\sum_{i = 1}^{X}a_i \geq \sum_{i = X + 1}^{n}a_i$,$X$就是最优解。

    这个东西叫做带权中位数

    丢一个百度百科的链接,里面有证明。                  传送门

    我自己把不严谨的证明在这里再写一遍:

      假设最优答案在$T$取到,那么有(唔,这里$a_i$代表权值):

          $\sum_{i = 1}^{n}a_i  *dis(i, T) \leq \sum_{i = 1}^{n}a_i * dis(i, T + 1)$

      变形一下:

          $\sum_{i = 1}^{T - 1}a_i  *dis(i, T) + \sum_{i = T + 1}^{n}a_i  *dis(i, T)  + a_{T + 1} * dis(T, T + 1)\leq \sum_{i = 1}^{T}a_i  *dis(i, T + 1) + \sum_{i = T + 2}^{n}a_i  *dis(i, T + 1)  + a_T * dis(T, T + 1)$

      

      发现$T$左边的点走到$T + 1$与走到$T$比,多走了$dis(T, T + 1)$,而右边的点则少走了$dis(T, T + 1)$。

      消掉一模一样的东西就得到了: $\sum_{i = 1}^{T}a_i \geq \sum_{i = T + 1}^{n}a_i$。

      把$T$和$T - 1$代进去也是一样的结果。

回到这题

  那么这题要求移到相邻的位置,可以理解为先移到同一个位置然后移回来,相对移动不变,我们只要找到这个带权中位数的位置,就能得到最优解了。

  带上修改,我们可以用两个树状数组来维护,一个维护$\sum_{i = 1}^{n}w_i$,另一个维护$\sum_{i = 1}^{n}w_i*(a_i - i)$,询问的时候先二分一下找到带权中位数的位置$pos$,然后对于$pos$左边的点向右移,对于$pos$右边的点向左移,就可以计算出答案了。

  时间复杂度$O(nlog^2{n})$。

Code:

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll; const int N = 2e5 + ;
const ll P = 1e9 + ; int n, qn;
ll a[N], w[N]; template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for(; ch > ''|| ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} namespace BitSum {
ll s[N]; #define lowbit(p) (p & (-p)) inline void modify(int p, ll v) {
for(; p <= n; p += lowbit(p))
s[p] += v;
} inline ll query(int p) {
ll res = 0LL;
for(; p > ; p -= lowbit(p))
res += s[p];
return res;
} inline ll getSum(int l, int r) {
if(r < l) return 0LL;
return query(r) - query(l - );
} } namespace BitMul {
ll s[N]; #define lowbit(p) (p & (-p)) inline void modify(int p, ll v) {
v %= P;
for(; p <= n; p += lowbit(p))
(s[p] = s[p] + v + P) %= P;
} inline ll query(int p) {
ll res = 0LL;
for(; p > ; p -= lowbit(p))
(res += s[p]) %= P;
return res;
} inline ll getSum(int l, int r) {
return (query(r) - query(l - ) + P) % P;
} } inline int getPos(int x, int y) {
int ln = x, rn = y, mid, res;
for(; ln <= rn; ) {
mid = (ln + rn) / ;
if(BitSum :: getSum(x, mid) >= BitSum :: getSum(mid + , y))
res = mid, rn = mid - ;
else ln = mid + ;
}
return res;
} inline ll abs(ll x) {
return x > ? x : -x;
} inline ll max(ll x, ll y) {
return x > y ? x : y;
} inline ll min(ll x, ll y) {
return x > y ? y : x;
} inline void solve(int x, int y) {
if(x == y) {
puts("");
return;
}
int pos = getPos(x, y);
/* ll res = BitMul :: getSum(x, y); //d1 = 0LL, d2 = 0LL;
d1 = (d1 - (BitSum :: getSum(pos, y) % P) * 1LL * abs(a[pos] - pos) % P + P) % P;
d1 = (d1 + (BitSum :: getSum(x, pos - 1) % P) * 1LL * abs(a[pos] - pos) % P + P) % P;
d2 = (d2 - (BitSum :: getSum(pos + 1, y) % P) * 1LL * abs(a[pos] - pos) % P + P) % P;
d2 = (d2 + (BitSum :: getSum(x, pos) % P) * 1LL * abs(a[pos] - pos) % P + P) % P;
ll d = 0LL;
d = (d - (BitSum :: getSum(pos, y) % P) * 1LL * abs(a[pos] - pos) % P + P) % P;
d = (d + (BitSum :: getSum(x, pos - 1) % P) * 1LL * abs(a[pos] - pos) % P + P) % P; */ ll res = 0LL;
res = (-BitMul :: getSum(x, pos) + (BitSum :: getSum(x, pos) % P) * abs(a[pos] - pos) % P + P) % P;
res = (res - (BitSum :: getSum(pos, y)) % P * abs(a[pos] - pos) % P + BitMul :: getSum(pos, y) + P) % P; // printf("%lld\n", (res + d + P) % P);
printf("%lld\n", res);
} int main() {
read(n), read(qn);
for(int i = ; i <= n; i++) read(a[i]);
for(int i = ; i <= n; i++) {
read(w[i]);
BitMul :: modify(i, w[i] * (a[i] - i));
BitSum :: modify(i, w[i]);
} for(int x, y; qn--; ) {
read(x), read(y);
if(x < ) {
x = -x;
BitSum :: modify(x, -w[x]);
BitMul :: modify(x, -1LL * w[x] * (a[x] - x));
w[x] = 1LL * y;
BitSum :: modify(x, w[x]);
BitMul :: modify(x, 1LL * w[x] * (a[x] - x));
} else solve(x, y);
} /* for(int i = 1; i <= n; i++)
printf("%lld ", BitSum :: getSum(i, i)); */ return ;
}

CF1030F Putting Boxes Together的更多相关文章

  1. 洛谷CF1030F Putting Boxes Together(树状数组)

    题意: 现在有n个物品,第i个物品他的位置在a[i],他的重量为w[i].每一个物品移动一步的代价为他的w[i].目前有2种操作: 1. x y 将第x的物品的重量改为y 2.l r 将编号在 [ l ...

  2. Codeforces 1053 C - Putting Boxes Together

    C - Putting Boxes Together 思路: 求带权中位数 用树状数组维护修改 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) ...

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

    Putting Boxes Together 题意: 现在有n个物品,第i个物品他的位置在a[i],他的重量为w[i].每一个物品移动一步的代价为他的w[i].目前有2种操作: 1. x y 将第x的 ...

  4. Codeforces 1053C Putting Boxes Together 树状数组

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF1053C.html 题目传送门 - CF1053C 题意 有 $n$ 个物品,第 $i$ 个物品在位置 $a ...

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

    #include <iostream> #include <algorithm> #include <cstdio> #include <math.h> ...

  6. 2018.09.24 codeforces 1053C. Putting Boxes Together(线段树)

    传送门 就是让你维护动态的区间带权中位数. 然而昨晚比赛时并没有调出来. 想找到带权中位数的中点可以二分(也可以直接在线段树上找). 也就是二分出第一个断点,使得断点左边的和恰好大于或等于断点右边的和 ...

  7. [CF1053C]Putting Boxes Together(线段树)

    http://codeforces.com/blog/entry/62013 两个结论: 1.一定有一个箱子不用动. 2.不动的箱子一定是加权前缀和为S/2的那个. 1显然,2由1易得. 于是问题变为 ...

  8. [Codeforces 1053C] Putting Boxes Together

    Link: Codeforces 1053C 传送门 Solution: 先推出一个结论: 最后必有一个点不动且其为权值上最中间的一个点 证明用反证证出如果不在中间的点必有一段能用代价少的替代多的 这 ...

  9. Technocup 2019 - Elimination Round 1

    http://codeforces.com/contest/1030 B. Vasya and Cornfield 判断点是否在矩形内(包括边界) 把每条边转化为一个不等式 public static ...

随机推荐

  1. spring MVC multipart处理文件上传

    在开发Web应用程序时比较常见的功能之一,就是允许用户利用multipart请求将本地文件上传到服务器,而这正是Grails的坚固基石——Spring MVC其中的一个优势.Spring通过对Serv ...

  2. Codeforces Round #259(div2)C(数学期望)

    数学题. 关键是求最大值为k时有多少种情况,结果是kn-(k-1)n-1.可以这么想:每一次都从1至k里选,共kn种,这里需要再减去每一次都从1至k-1里面选的情况.当然也可以分类计数法:按出现几次k ...

  3. javascript版前端页面RSA非对称加密解密

    最近由于项目需要做一个url传参,并在页面显示参数内容的需求,这样就会遇到一个url地址可能会被假冒, 并传递非法内容显示在页面的尴尬情况 比如xxx.shtml?server=xxx是坏人& ...

  4. MySQL_截止昨日南京市所有在职业务员业绩排名-20170116

    #计算南京销售员总业绩排名 数据结果已打乱处理 #职工信息表包含在职和离职两种状态 因此不能以这表当做主表 不然离职人的数据也会出现 以毛利表为主表 销售员限制在昨天在职的销售范围内 且和后面left ...

  5. 安装成功的nginx如何添加未编译模块?

    在重启nginx后发生了错误,错误如下: nginx: [emerg] the "ssl" parameter requires ngx_http_ssl_module in /u ...

  6. HDU1576(扩展欧几里得)

    A/B Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  7. Anti-pattern(反模式)

    常见的与“直觉”相背离的 anti-pattern 产生的实际原因是我们没有深入全面地考虑问题. 即只关注到自己关心的方面,忽略了其他重要的.恰好起相反作用的因素. 所以这个“直觉”是不成熟.不全面的 ...

  8. 第十四届华中科技大学程序设计竞赛决赛同步赛 F Beautiful Land(01背包,背包体积超大时)

    链接:https://www.nowcoder.com/acm/contest/119/F来源:牛客网 Beautiful Land 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 1 ...

  9. centos7的xfs配置

    XFS是扩展性高.高性能的文件系统.也是rhel7/centos7的默认文件系统.XFS支持metadata journaling,这使其能从crash中更快速的恢复.它也支持在挂载和活动的状态下进行 ...

  10. c:if标签数据回显判断是否选中

    <form action="/brand/list.do" method="post" style="padding-top:5px;" ...