题意:
现在有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]上,记录下花费。
然后在把这一整段的物品整体移动到对应区间就好了。
注意的就是对于中间点来说,整体区间移动的正负是不一样的。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include2 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<<110 #define rson m+1,r,rt<<1|111 #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 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 }