2018 Multi-University Training Contest 3
二维平面上给出n=1e5个有权值w=1e9的点,且x坐标刚好从1到n各不相同,1<=y<=n。现在m=1e6的询问,每个询问给出一个矩形,问矩形内所有点的权值积、最大值、最小值。
查询离线,并按x轴进行分治。当前矩形刚好覆盖分治的中线时,由于这些矩形一边已经固定,所以用线段树扫两遍即可,这样查询就只有一个log。时间复杂度O((n log n + m) log n)。注意撤销的时候碰到未标记的部分就返回。
#include<bits/stdc++.h>
using namespace std;
#define lc o<<1
#define rc o<<1|1
#define fi first
#define se second
#define pb push_back
#define ALL(X) (X).begin(), (X).end()
#define bcnt(X) __builtin_popcountll(X)
#define CLR(A, X) memset(A, X, sizeof(A))
#pragma comment(linker, "/STACK:1024000000,1024000000")
using DB = double;
using LL = long long;
using PII = pair<int, int>;
const int INF = 0x3f3f3f3f;
const int N = 1e5+10, M = 1e6+10;
int MOD;
void input(int n, int &m);
inline int umin(const int &x, const int &y) { return x<y?x:y; }
inline int umax(const int &x, const int &y) { return x>y?x:y; }
int qid, ql, qr, qv;
int prod[M], mx[M], mn[M];
struct Node{ int l, r, mn, mx, s; } T[N<<2];
inline void pushup(int o) {
T[o].s = 1LL*T[lc].s*T[rc].s%MOD;
T[o].mn = min(T[lc].mn, T[rc].mn);
T[o].mx = max(T[lc].mx, T[rc].mx);
}
void build(int o, int l, int r) {
T[o].mn = INF, T[o].mx = -INF, T[o].s = 1;
if((T[o].l=l) == (T[o].r=r)) return;
int mid = l+r>>1;
build(lc, l, mid); build(rc, mid+1, r);
}
void clean(int o = 1) {
if(T[o].mn == INF) return;
T[o].mn = INF, T[o].mx = -INF, T[o].s = 1;
if(T[o].l == T[o].r) return;
clean(lc); clean(rc);
}
void update(int o = 1) {
if(T[o].l == T[o].r) {
T[o].mn = umin(T[o].mn, qv);
T[o].mx = umax(T[o].mx, qv);
T[o].s = 1LL*T[o].s*qv%MOD;
return;
}
int mid = T[o].l+T[o].r>>1;
if(ql <= mid) update(lc); else update(rc);
pushup(o);
}
void query(int o = 1) {
if(T[o].mn == INF) return;
if(ql<=T[o].l && qr>=T[o].r) {
prod[qid] = 1LL*prod[qid]*T[o].s%MOD;
mn[qid] = umin(mn[qid], T[o].mn);
mx[qid] = umax(mx[qid], T[o].mx);
return;
}
int mid = T[o].l+T[o].r>>1;
if(ql <= mid) query(lc); if(qr > mid) query(rc);
}
struct RECT {
int xl, xr, yl, yr, id;
void print() {
printf("id=%d xl=%d xr=%d yl=%d yr=%d\n", id, xl, xr, yl, yr);
}
}rec[M], pool[M], b[M];
inline bool cmpl(const RECT &A, const RECT &B) { return A.xl > B.xl; }
inline bool cmpr(const RECT &A, const RECT &B) { return A.xr < B.xr; }
PII hou[N];
void solve(int nl, int nr, int ml, int mr) {
if(nl>nr || ml>mr) return;
int nm = nl+nr>>1, dl = ml-1, dr = mr+1, k = 0;
for(int i = ml; i <= mr; i++) {
if(rec[i].xr < nm) pool[++dl] = rec[i];
else if(rec[i].xl > nm) pool[--dr] = rec[i];
else b[k++] = rec[i];
}
sort(b, b+k, cmpl);
int j = nm;
for(int i = 0; i < k; i++) {
while(j >= b[i].xl) {
ql = hou[j].fi; qv = hou[j--].se;
update();
}
ql = b[i].yl, qr = b[i].yr, qid = b[i].id;
query();
}
clean();
sort(b, b+k, cmpr);
j = nm+1;
for(int i = 0; i < k; i++) {
while(j <= b[i].xr) {
ql = hou[j].fi; qv = hou[j++].se;
update();
}
ql = b[i].yl, qr = b[i].yr, qid = b[i].id;
query();
}
clean();
for(int i = ml; i <= dl; i++) rec[i] = pool[i];
for(int i = dr; i <= mr; i++) rec[i] = pool[i];
solve(nl, nm-1, ml, dl); solve(nm+1, nr, dr, mr);
}
int main() {
int X;
scanf("%d", &X);
while(X--) {
int n, m;
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d%d", &hou[i].fi, &hou[i].se);
}
input(n, m);
build(1, 1, n);
solve(1, n, 1, m);
LL ans = 0;
for(int i = 1; i <= m; i++) {
if(mn[i] == INF) continue;
ans += prod[i]^mx[i]^mn[i];
// printf("ans = %d %d %d\n", prod[i], mx[i], mn[i]);
}
printf("%lld\n", ans);
}
return 0;
}
void input(int n, int &m) {
int a[2], b[2], c[2], d[2], p, q, r, P;
scanf("%d %d%d%d%d %d%d%d%d %d", &m, a,b,c,d, &p,&q,&r,&P, &MOD);
auto get = [&](const int &x, const int &y)->int { return (1LL*p*x+1LL*q*y+r)%P; };
for(int i = 1; i <= m; i++) {
a[1] = get(a[0], b[0]); b[1] = get(b[0], a[0]);
c[1] = get(c[0], d[0]); d[1] = get(d[0], c[0]);
a[0] = a[1], b[0] = b[1], c[0] = c[1], d[0] = d[1];
rec[i].xl = umin(a[0]%n, b[0]%n)+1;
rec[i].xr = umax(a[0]%n, b[0]%n)+1;
rec[i].yl = umin(c[0]%n, d[0]%n)+1;
rec[i].yr = umax(c[0]%n, d[0]%n)+1;
rec[i].id = i;
prod[i] = 1, mn[i] = INF, mx[i] = -INF;
// rec[i].print();
}
}