1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
| struct SegTree { struct data { ll minv, cnt; }; struct lztag { int v; }; typedef data T; typedef int Lz;
#define M ((L+R)>>1)
int LEFT, RIGHT; vector<T> sumv;
vector<Lz> tag; vector<int> ls, rs; vector<int> raw; T add(T a, T b,int L, int R) { if (a.minv == b.minv) return {a.minv, a.cnt + b.cnt}; if (a.minv < b.minv) return {a.minv, a.cnt + raw[R]-raw[M]}; return {b.minv, b.cnt + raw[M]-raw[L-1]}; } T addt(T a, Lz b, int o, int l, int r) { a.minv += b; return a; } Lz addtt (Lz a, Lz b) { return a + b; }
T zeroT = {0,0}; Lz zeroLz = 0; SegTree(int left, int right) : LEFT(left), RIGHT(right), sumv(1), tag(1), ls(1), rs(1) {} SegTree(vector<int>& raw) : LEFT(1), RIGHT(sz(raw)-1), sumv(1), tag(1), ls(1), rs(1), raw(raw) {}
inline int getpos(int x) { return lower_bound(raw.begin(), raw.end(), x) - raw.begin(); }
inline void pushdown(int o, int L, int R) { if (L != R && !ls[o]) newnode(o); if (L == R || tag[o] == zeroLz) return; sumv[ls[o]] = addt(sumv[ls[o]], tag[o],o, L, M); sumv[rs[o]] = addt(sumv[rs[o]], tag[o],o, M+1, R); tag[ls[o]] = addtt(tag[ls[o]], tag[o]); tag[rs[o]] = addtt(tag[rs[o]], tag[o]); tag[o] = zeroLz; }
void newnode(int o) { sumv.push_back(zeroT); sumv.push_back(zeroT); tag.push_back(zeroLz); tag.push_back(zeroLz); ls.push_back(0); ls.push_back(0); rs.push_back(0); rs.push_back(0); ls[o] = sz(sumv)-2; rs[o] = sz(sumv)-1; }
inline void insert(int x, Lz val, int o=0, int L=1, int R=-1) { if (R == -1) {L = LEFT; R = RIGHT; x = getpos(x); } if (L == R) sumv[o] = addt(sumv[o], val,o, L, R); else { pushdown(o, L, R); if (x <= M) insert(x, val, ls[o], L, M); else insert(x, val, rs[o], M+1, R); sumv[o] = add(sumv[ls[o]], sumv[rs[o]],L,R); } }
inline void update(int x, int y, Lz val, int o=0, int L=1, int R=-1) { if (R == -1) {L = LEFT; R = RIGHT; if (!raw.empty()) x = getpos(x)+1, y = getpos(y); } if (x <= L && R <= y) sumv[o] = addt(sumv[o], val,o, L, R), tag[o] = addtt(tag[o], val); else { pushdown(o, L, R); if (x <= M) update(x, y, val, ls[o], L, M); if (y > M) update(x, y, val, rs[o], M+1, R); sumv[o] = add(sumv[ls[o]], sumv[rs[o]],L,R); } }
inline T query(int x=-1, int y=-1, int o=0, int L=1, int R=-1) { if (R == -1) {L = LEFT; R = RIGHT; if (x==-1) x=LEFT,y=RIGHT; else if (!raw.empty()) x = getpos(x)+1, y = getpos(y); } pushdown(o, L, R); if (x <= L && R <= y) return sumv[o]; else if (x <= M && y > M) return add(query(x, M, ls[o], L, M), query(M+1, y, rs[o], M+1, R),L,R); else if (x <= M) return query(x, y, ls[o], L, M); else return query(x, y, rs[o], M+1, R); } };
ll sweepline(vector<tuple<int,int,int,int>>& A) { struct Line { ll y1, y2, x, k; bool operator<(const Line& l) const { if (x == l.x) return k > l.k; return x < l.x; } }; vector<Line> v; vector<int> B; for (auto [x1,y1,x2,y2] : A) { v.push_back({y1,y2,x1,1}); v.push_back({y1,y2,x2,-1}); B.push_back(y1); B.push_back(y2); } sort(v.begin(), v.end()); sort(B.begin(), B.end()); int nm = unique(B.begin(), B.end()) - B.begin(); while (sz(B) != nm) B.pop_back(); SegTree seg(B); ll prex = 0; ll ans = 0; for (auto [y1,y2,x,k] : v) { auto [minv, cnt] = seg.query(); cnt = minv ? B.back()-B[0] : cnt; ans += (x - prex)*cnt; seg.update(y1,y2, k); prex = x; } return ans; }
|