二分找到分界点, 左边的往右移, 右边的往左移。
其实把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 #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ALL(x) (x).begin(), (x).end() #define fio ios::sync_with_stdio(false); cin.tie(0); using namespace std; const int N = 2e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; const double PI = acos(-1); template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;} template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;} template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;} template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;} int n, q, a[N], w[N]; struct Bit { LL a[N]; void modify(int x, int v) { for(int i = x; i <= n; i += i & -i) a[i] += v; } LL sum(int x) { LL ans = 0; for(int i = x; i; i -= i & -i) ans += a[i]; return ans; } LL query(int L, int R) { if(L > R) return 0; return sum(R) - sum(L - 1); } } bit; struct Bit2 { int a[N]; void modify(int x, int v) { for(int i = x; i <= n; i += i & -i) add(a[i], v); } int sum(int x) { LL ans = 0; for(int i = x; i; i -= i & -i) add(ans, a[i]); return ans; } int query(int L, int R) { if(L > R) return 0; return (sum(R) - sum(L - 1) + mod) % mod; } } prefix, suffix; int main() { LL ret = 0; scanf("%d%d", &n, &q); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = 1; i <= n; i++) scanf("%d", &w[i]); for(int i = 1; i <= n; i++) { bit.modify(i, w[i]); prefix.modify(i, 1LL * abs(a[i] - a[1] - i + 1) * w[i] % mod); } for(int i = n; i >= 1; i--) suffix.modify(i, 1LL * abs(a[n] - a[i] - n + i) * w[i] % mod); while(q--) { int x, y; scanf("%d%d", &x, &y); if(x < 0) { x = -x; bit.modify(x, -w[x]); prefix.modify(x, mod - (1LL * abs(a[x] - a[1] - x + 1) * w[x] % mod)); suffix.modify(x, mod - (1LL * abs(a[n] - a[x] - n + x) * w[x] % mod)); w[x] = y; bit.modify(x, w[x]); prefix.modify(x, 1LL * abs(a[x] - a[1] - x + 1) * w[x] % mod); suffix.modify(x, 1LL * abs(a[n] - a[x] - n + x) * w[x] % mod); } else { int len = y - x + 1; int low = a[x], high = a[y], p = low, low2, high2, p2, fen; while(low <= high) { int mid = low + high >> 1; low2 = x, high2 = y, p2 = y + 1; while(low2 <= high2) { int mid2 = low2 + high2 >> 1; if(a[mid2] > mid + mid2 - x) p2 = mid2, high2 = mid2 - 1; else low2 = mid2 + 1; } LL valL = bit.query(x, p2 - 1); LL valR = bit.query(p2, y); if(valL > valR) p = mid, high = mid - 1, fen = p2; else low = mid + 1; } LL ans = 0; if(fen <= y) { add(ans, prefix.query(fen, y)); sub(ans, bit.query(fen, y) % mod * (p - (a[1] + x - 1)) % mod); } if(fen - 1 >= x) { add(ans, suffix.query(x, fen - 1)); sub(ans, bit.query(x, fen - 1) % mod * (a[n] - (n - x) - p) % mod); } printf("%lld\n", ans); } } return 0; } /* */