随机、随机、随机
维护l,r分别表示每块木板向走向右第一个比它高的。
修改x,l,r无变化。
修改y
1.拔高:
按原来的l,r往左右跳,维护一下。
2.降低:
如果x-1的高度小于x,则从x-1开始,一直跳l,同时维护它们的r。
右边的同理。
查询:
结论是答案一定在x的r链和y的l链上,用个单调栈维护一下,复杂度为链长。
由于是随机数据,所以链长期望是log的,因此总复杂度为O(n log n)
我嫌麻烦,不是这么打的,暴力往左和往右移就过了,复杂度也许是O(n^2 / log n)?
Code:
#include
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define fd(i, x, y) for(int i = x; i >= y; i --)
#define abs(a) ((a) > 0 ? (a) : -(a))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
using namespace std;
const int N = 5e5 + 5;
int n, q, a[N], b[N], l[N], r[N], u[N], v[N];
int num, x, y, p;
int ql(int x) {
int p = x;
while(b[p] <= b[x]) p --;
return p;
}
int qr(int x) {
int p = x;
while(b[p] <= b[x]) p ++;
return p;
}
int main() {
freopen("board.in", "r", stdin);
freopen("board.out", "w", stdout);
scanf("%d %d", &n, &q);
fo(i, 1, n) scanf("%d", &a[i]);
fo(i, 1, n) scanf("%d", &b[i]);
b[0] = b[n + 1] = 2e9;
fo(i, 1, n) l[i] = ql(i), r[i] = qr(i);
fo(ii, 1, q) {
scanf("%d %d %d", &num, &x, &y);
if(num == 3) {
a[x] = y;
} else
if(num == 2) {
b[x] = y;
l[x] = ql(x);
r[x] = qr(x);
fo(i, l[x] + 1, x - 1) r[i] = qr(i);
fo(i, x + 1, r[x] - 1) l[i] = ql(i);
} else {
u[0] = v[0] = 0;
p = x;
while(p <= y) u[++ u[0]] = p, p = r[p];
if(u[u[0]] > n) u[0] --;
p = y;
while(p >= x) v[++ v[0]] = p, p = l[p];
if(v[v[0]] < 1) v[0] --;
ll ans = 0;
fo(i, 1, u[0]) fo(j, 1, v[0])
ans = max(ans, (ll) min(b[u[i]], b[v[j]]) * abs(a[u[i]] - a[v[j]]));
printf("%lld\n", ans);
}
}
}