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 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
| #include <bits/stdc++.h> using namespace std; using i64 = long long; using i128 = __int128_t; constexpr int maxm = 3e7; vector<int> sx, sy; struct Segment { struct Node { int mn, mncnt, ls, rs; int del, tag; i64 mnsum; }a[maxm]; struct info { int mn, mncnt; i64 mnsum; friend info operator + (info x, info y) { info z; z.mn = min(x.mn, y.mn); z.mnsum = x.mnsum + y.mnsum; if(x.mn < y.mn) z.mncnt = x.mncnt; else if(x.mn > y.mn) z.mncnt = y.mncnt; else z.mncnt = x.mncnt + y.mncnt; return z; } info apply(int del, int tag, int is) { return {mn + del, mncnt, mnsum + (mn + del == is ? 1ll * tag * mncnt: 0) }; } }; int cnt; inline int newnode(int u) { int cur = ++ cnt; assert(cnt < maxm - 10); a[cur] = a[u]; return cur; } inline void seta(int u, int del, int tag, int is) { a[u].del += del; a[u].mn += del; if(a[u].mn == is) { a[u].mnsum += 1ll * a[u].mncnt * tag; a[u].tag += tag; } } inline void dw(int u) { a[u].ls = newnode(a[u].ls); seta(a[u].ls, a[u].del, a[u].tag, a[u].mn); a[u].rs = newnode(a[u].rs); seta(a[u].rs, a[u].del, a[u].tag, a[u].mn); a[u].del = a[u].tag = 0; } inline void up(int u) { a[u].mn = min(a[a[u].ls].mn, a[a[u].rs].mn); if(a[a[u].ls].mn < a[a[u].rs].mn) a[u].mncnt = a[a[u].ls].mncnt; else if(a[a[u].ls].mn > a[a[u].rs].mn) a[u].mncnt = a[a[u].rs].mncnt; else a[u].mncnt = a[a[u].ls].mncnt + a[a[u].rs].mncnt; } void update(int &u, int l, int r, int ql, int qr, int k) { u = newnode(u); if(l >= ql && r <= qr) return seta(u, k, 0, 0); int mid = l + r >> 1; dw(u); if(qr <= mid) update(a[u].ls, l, mid, ql, qr, k); else if(ql > mid) update(a[u].rs, mid + 1, r, ql, qr, k); else update(a[u].ls, l, mid, ql, qr, k), update(a[u].rs,mid + 1, r, ql, qr, k); up(u); } info query(int u, int l, int r, int ql, int qr) { if(l >= ql && r <= qr) return info{a[u].mn, a[u].mncnt, a[u].mnsum}; int mid = l + r >> 1; if(qr <= mid) return query(a[u].ls, l, mid, ql, qr).apply(a[u].del, a[u].tag, a[u].mn); else if(ql > mid) return query(a[u].rs, mid + 1, r, ql, qr).apply(a[u].del, a[u].tag, a[u].mn); else return (query(a[u].ls, l, mid, ql, qr) + query(a[u].rs, mid + 1, r, ql, qr)).apply(a[u].del, a[u].tag, a[u].mn); } void build(int &u, int l, int r) { u = newnode(0); if(l == r) { a[u].mncnt = sy[l + 1] - sy[l]; return ; } int mid = l + r >> 1; build(a[u].ls, l, mid), build(a[u].rs, mid + 1, r); up(u); } }ds; int main() {
ios::sync_with_stdio(false), cin.tie(0); int r, c, n, q; cin >> r >> c >> n >> q; vector<array<int, 4>> mat(n); for(int i = 0; i < n; i ++) { for(int j = 0; j < 4; j ++) cin >> mat[i][j]; if(mat[i][0] == mat[i][2] || mat[i][1] == mat[i][3]) { i --, n --; continue; } if(mat[i][0] > mat[i][2]) swap(mat[i][0], mat[i][2]); if(mat[i][1] > mat[i][3]) swap(mat[i][1], mat[i][3]); sx.push_back(mat[i][0]), sx.push_back(mat[i][2]); sy.push_back(mat[i][1]), sy.push_back(mat[i][3]); } sx.push_back(-1), sy.push_back(-1); sx.push_back(r + 1), sy.push_back(c + 1); sort(sx.begin(), sx.end()), sx.erase(unique(sx.begin(), sx.end()), sx.end()); sort(sy.begin(), sy.end()), sy.erase(unique(sy.begin(), sy.end()), sy.end()); vector<vector<array<int, 3>>> upd(sx.size()); vector<int> rt(sx.size()); for(int i = 0; i < n; i ++) { for(int j = 0; j < 4; j ++) { if(j & 1) mat[i][j] = lower_bound(sy.begin(), sy.end(), mat[i][j]) - sy.begin(); else mat[i][j] = lower_bound(sx.begin(), sx.end(), mat[i][j]) - sx.begin(); } upd[mat[i][0]].push_back({mat[i][1], mat[i][3] - 1, 1}); upd[mat[i][2]].push_back({mat[i][1], mat[i][3] - 1, -1}); } ds.build(rt[0], 0, sy.size() - 2); for(int i = 1; i < sx.size(); i ++) { rt[i] = rt[i - 1]; ds.seta(rt[i], 0, sx[i] - sx[i - 1], 0); for(auto u : upd[i]) ds.update(rt[i], 0, sy.size() - 2, u[0], u[1], u[2]); } i64 lstans = 0; int tot = 0; for(int i = 0; i < q; i ++) { int x1, x2, y1, y2; i64 v; cin >> x1 >> y1 >> x2 >> y2 >> v; x1 = (x1 + i128(v) * lstans) % (r + 1); x2 = (x2 + i128(v) * lstans) % (r + 1); y1 = (y1 + i128(v) * lstans) % (c + 1); y2 = (y2 + i128(v) * lstans) % (c + 1); if(x1 == x2 || y1 == y2) { cout << (lstans = 0) << '\n'; continue; } if(x1 > x2) swap(x1, x2); if(y1 > y2) swap(y1, y2); int u1 = lower_bound(sx.begin(), sx.end(), x1) - sx.begin(), u2 = upper_bound(sx.begin(), sx.end(), x2) - sx.begin() - 1; int v1 = lower_bound(sy.begin(), sy.end(), y1) - sy.begin(), v2 = upper_bound(sy.begin(), sy.end(), y2) - sy.begin() - 1; auto calcy = [&] (int u1, int u2) { auto calc = [&] (int v1, int v2) { return ds.query(rt[u2], 0, sy.size() - 2, v1, v2).mnsum - (u1 ? ds.query(rt[u1 - 1], 0, sy.size() - 2, v1, v2).mnsum : 0); }; if(v1 > v2) { i64 ans = calc(v2, v2) / (sy[v1] - sy[v2]) * (y2 - y1); return ans; } else { i64 ans = (sy[v1] - y1 ? calc(v1 - 1, v1 - 1) / (sy[v1] - sy[v1 - 1]) * (sy[v1] - y1) : 0) + (y2 - sy[v2] ? calc(v2, v2) / (sy[v2 + 1] - sy[v2]) * (y2 - sy[v2]) : 0); if(v1 < v2) ans += calc(v1, v2 - 1); return ans; } }; if(u1 > u2) { i64 ans = calcy(u2, u2) / (sx[u1] - sx[u2]) * (x2 - x1); cout << (lstans = 1ll * (x2 - x1) * (y2 - y1) - ans) << '\n'; } else { i64 ans = (sx[u1] - x1 ? calcy(u1 - 1, u1 - 1) / (sx[u1] - sx[u1 - 1]) * (sx[u1] - x1) : 0) + (x2 - sx[u2] ? calcy(u2, u2) / (sx[u2 + 1] - sx[u2]) * (x2 - sx[u2]) : 0); if(u1 < u2) ans += calcy(u1, u2 - 1); cout << (lstans = 1ll * (x2 - x1) * (y2 - y1) - ans) << '\n'; } } return 0; }
|