CodeForces 1058 F 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 }