题意是:按时间先后有许多左下角固定为(0,0),右上角为(xi,yi)的矩形浪潮,每次浪潮会留下痕迹,但是后来的浪潮又会冲刷掉自己区域的老痕,留下新痕迹,问最后留下的痕迹长度为多少?
这题里,不存在2个浪潮,使得一个浪潮完全被另一个覆盖.
如图,经过了(1,4),(4,1),(3,3)浪潮后,所留下的痕迹(红边为10).
每次浪潮都会有贡献.再而,如果浪潮在时间上从前往后考虑,则不能知悉当前浪潮会被以后的多少浪潮影响.所以从后往前考虑,可以把握每次浪潮带给当前浪潮的影响.
其次,时间上从后往前考虑,对于当前浪潮在x方向的贡献,必然是没有被前面所考虑的(时间上在后面的)的浪潮所覆盖的部分.那么什么样的浪潮会覆盖掉自己的x边?比自己高的浪都会覆盖自己的x边,覆盖被覆盖的最多的,也就是>y的那些浪中,x最大的那个.
总结一下:对于当前的浪(xi,yi),xi边的贡献是xi-x,其中x是>yi的浪中,x坐标最大的浪.
yi边的贡献是yi-y,其中y是>xi的浪中,y最大的浪.
为什么不是>= ? 因为如果有两个浪的x或者y相同的话,必然有一个浪被包含于另外一个浪中,这不符合题意.
问题演变成区间查询和点更新,线段树解决即可:
#include <bits/stdc++.h> using namespace std; #define ll long long #define FOR(i,a,b) for(int i=(a);i<=(b);++i) #define DOR(i,a,b) for(int i=(a);i>=(b);--i) const int maxN=1e6+5; int N, M, K, T; int le[maxN], ri[maxN], A[maxN]; int gx[maxN<<2], gy[maxN<<2]; #define lson l,m,rt*2 #define rson m+1,r,rt*2+1 void update(int op, int p, int c, int l, int r, int rt) { if (l == r) { if (op == 1) gx[rt] = max(c, gx[rt]); else gy[rt] = max(c, gy[rt]); return; } int m = (l + r) / 2; int lch = rt * 2, rch = lch + 1; if (p <= m) update(op, p, c, lson); else update(op, p, c, rson); // push_up if (op == 1) gx[rt] = max(gx[lch], gx[rch]); else gy[rt] = max(gy[lch], gy[rch]); } int query(int op, int L, int R, int l, int r, int rt) { if (L <= l && r <= R) { if (op == 1) return gx[rt]; else return gy[rt]; } int m = (l + r) / 2; int ans = 0; if (L <= m) ans = max(ans, query(op, L, R, lson)); if (R > m) ans = max(ans, query(op, L, R, rson)); return ans; } int main () { scanf("%d", &N); int k = 0; FOR(i, 1, N) { scanf("%d%d", &le[i], &ri[i]); A[k++] = le[i], A[k++] = ri[i]; } sort(A, A + k); k = unique(A, A + k) - A; // Build Segment Tree memset(gx, 0, sizeof gx); memset(gy, 0, sizeof gy); ll ans = 0; DOR(i, N, 1) { int a = le[i], b = ri[i]; le[i] = lower_bound(A, A + k, le[i]) - A + 1; ri[i] = lower_bound(A, A + k, ri[i]) - A + 1; int my = query(1, le[i], k, 1, k, 1); int mx = query(2, ri[i], k, 1, k, 1); ans += (b - my) + (a - mx); update(1, le[i], A[ri[i] - 1], 1, k, 1); update(2, ri[i], A[le[i] - 1], 1, k, 1); } printf("%lld ", ans); return 0; }