P8868 [NOIP2022] 比赛
求$$\sum_{p = l}^{r} \sum_{q =p}^{r} (\max_{p \le i \le q}a_i)(\max_{p \le j \le q}b_j)$$
有比较套路的扫描线做法。令 $f_i = \sum_{p =i}^{r}(\max_{p \le i \le r}a_i)(\max_{p \le j \le r}b_j)$。
线段树上维护 $S_{l} = \sum_{i=l}^{r}f_i$。我们将询问离线,从左向右扫描。
当扫描到 $i$ 时,记 $ap_i = \max_{1 \le k < i} k + 1,(a_k \ge a_i)$,同理也有 $bp_i$。
不妨设 $ap_i \le bp_i$。
我们发现,对于线段树上区间 $1 \sim ap_i$ 他们和之前一样增长。
对于 $ap_i + 1 \sim bp_i$ 增长变为 $a_i \times b_{bp_i}$。
超过 $bp_i$ 后变为 $a_i \times b_i$。总共有 $2 \times n$ 个断点,这可以用单调栈维护。
设计双半群模型:
我们设计 $D + D \to D$, $M \times D \to D$, $M \times M \to M$
对于如何维护标记,有比较方便的做法:直接维护一个多项式。最高次项是 $\sum a_i \times b_i$,所以我们维护半群 $D(X_i \times Y_i,X_i,Y_i,S,len)$。
然后是 $M(A_{x\times y},A_x,A_y,C_x,C_y,C)$。
咕咕咕.
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N = 2.5e5 + 500;
int T, n, q;
int a[N], b[N];
struct info{
ull sxy, sx, sy, s;
//info(ull sxy, ull sx, ull sy, ull s) : sxy(sxy), sx(sx), sy(sy), s(s) {}
bool empty() {return !(sxy || sx || sy || s);}
void clear() {sxy = sx = sy = s = 0;}
void de_b() {printf("%llu %llu %llu %llu\n", s, sx, sy, sxy);}
};
struct tag{
ull axy, ax, ay, cx, cy, c;
//tag(ull axy, ull ax, ull ay, ull cx, ull cy, ull c) : axy(axy), ax(ax), ay(ay), cx(cx), cy(cy), c(c) {}
bool empty() {return !(axy || ax || ay || cx || cy || c);}
void clear() {axy = ax = ay = cx = cy = c = 0;}
void de_b() {printf("%llu %llu %llu %llu %llu %llu\n",cx,cy,ax,ay,axy,c);}
};
info merge(info x, info y) {
x.sxy += y.sxy;
x.sx += y.sx;
x.sy += y.sy;
x.s += y.s;
return x;
}
tag merge(tag x, tag y) {
if(y.cx && y.cy) y.c += x.c + x.axy * y.cx * y.cy + x.ax * y.cx + x.ay * y.cy;
else if(y.cx) {
y.ay += x.ay + y.cx * x.axy;
y.c += x.c + x.ax * y.cx;
} else if(y.cy) {
y.ax += x.ax + y.cy * x.axy;
y.c += x.c + x.ay * y.cy;
} else {
y.axy += x.axy;
y.ax += x.ax;
y.ay += x.ay;
y.c += x.c;
}
if(x.cx) y.cx = x.cx;
if(x.cy) y.cy = x.cy;
return y;
}
info merge(info x, tag y, int len) {
x.s += x.sxy * y.axy + x.sx * y.ax + x.sy * y.ay + y.c * len;
if(y.cx && y.cy) {
x.sx = y.cx * len;
x.sy = y.cy * len;
x.sxy = y.cx * y.cy * len;
} else if(y.cx) {
x.sxy = y.cx * x.sy;
x.sx = y.cx * len;
} else if(y.cy) {
x.sxy = y.cy * x.sx;
x.sy = y.cy * len;
}
return x;
}
#define lc k << 1
#define rc lc | 1
#define lcon lc, l, mid
#define rcon rc, mid + 1, r
#define Mid int mid = l + r >> 1
info tem[N << 2];
tag ad [N << 2];
void p_up(int k) {
tem[k] = merge(tem[lc], tem[rc]);
//tem[k].de_b();
}
void Ad(int k, int l, int r, tag a) {
//tem[k].de_b();
ad[k] = merge(a, ad[k]);
tem[k] = merge(tem[k], a, r - l + 1);
//tem[k].de_b();
}
void p_do(int k, int l, int r) {
if(!ad[k].empty()) {
Mid;
//ad[k].de_b();
Ad(lcon, ad[k]), Ad(rcon, ad[k]);
ad[k].clear();
}
}
void modify(int k, int l, int r, int x, int y, tag a) {
if(x <= l && r <= y) {
//cout << "Pre\n"; ad[k].de_b(), tem[k].de_b();
Ad(k, l, r, a);
//ad[k].de_b();
//tem[k].de_b();
return;
}
Mid; p_do(k, l, r); if(x <= mid) modify(lcon, x, y, a);
if(y > mid) modify(rcon, x, y, a); p_up(k);
}
ull query(int k, int l, int r, int x, int y) {
if(x <= l && r <= y) return tem[k].s; ull res = 0;
Mid; p_do(k, l, r); if(x <= mid) res += query(lcon, x, y);
if(y > mid) res += query(rcon, x, y); return res;
}
struct node{
int l, r, id;
node(int l, int r, int id) : l(l), r(r), id(id) {}
};
int sta[N], ta;
int stb[N], tb;
ull ans[N];
vector< node > qr[N];
int main() {
scanf("%d %d", &T, &n);
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
for(int i = 1; i <= n; ++i) scanf("%d", &b[i]);
scanf("%d", &q);
for(int i = 1; i <= q; ++i) {
int l, r;
scanf("%d %d", &l, &r);
qr[r].push_back(node(l, r, i));
}
for(int i = 1; i <= n; ++i) {
while(ta && a[sta[ta]] < a[i]) ta--;
//cout << "Add: "; tem[1].de_b();
modify(1, 1, n, sta[ta] + 1, i, tag{0, 0, 0, (ull)a[i], 0, 0});
//cout << "End: "; tem[1].de_b();
sta[++ta] = i;
while(tb && b[stb[tb]] < b[i]) tb--;
//cout << "Add: "; tem[1].de_b();
modify(1, 1, n, stb[tb] + 1, i, tag{0, 0, 0, 0, (ull)b[i], 0});
//cout << "End: "; tem[1].de_b();
stb[++tb] = i;
modify(1, 1, n, 1, i, tag{1, 0, 0, 0, 0, 0});
//tem[1].de_b();
for(auto E : qr[i]) ans[E.id] = query(1, 1, n, E.l, i);
}
for(int i = 1; i <= q; ++i) printf("%llu\n", ans[i]);
return 0;
}
习题: rsraogps

浙公网安备 33010602011771号