题目链接:T2238 礼物
考虑 $[l,r]$ 区间中哪些二元组是优秀二元组:
发现将二元组的 $x$ 按照从大到小排序,若 $y[i]$ 是这个前缀的最大值,则该二元组是优秀的.
因为数据是随机的,所以前缀最大值期望是 $log(n)$ 个的.
所以,我们可以用线段树来暴力存这些优秀的二元组.
区间合并 $pushup$ 时运用类似归并排序的方式来进行合并即可.
由于优秀二元组期望的数量是 $log$ 的,所以空间最多只会在原基础上乘一个 $log$.
我的归并写的好丑~
#include <cstdio> #include <algorithm> #include <cstring> #include <vector> #define N 200006 #define ll long long #define mod 1000000007 #define lson t[now].ls #define rson t[now].rs #define siz (t[now].v.size() - 1) #define setIO(s) freopen(s".in", "r" , stdin) , freopen(s".out", "w", stdout) using namespace std; int n ; struct P { ll x , y; P(ll x = 0, ll y = 0) : x(x), y(y) {} }p[N]; struct Node { int ls, rs ; vector <P> v; }t[N << 2]; vector <P> G, V, A; inline void pushup(int L, int R, int now) { if(!rson) { t[now].v = t[lson].v; } else { int p1 = 0, p2 = 0; while(p1 < t[lson].v.size() && p2 < t[rson].v.size()) { if(t[lson].v[p1].x == t[rson].v[p2].x && t[lson].v[p1].y == t[rson].v[p2].y) ++p1, ++p2; else if(t[lson].v[p1].x >= t[rson].v[p2].x && t[lson].v[p1].y >= t[rson].v[p2].y || t[lson].v[p1].x > t[rson].v[p2].x) { if(t[now].v.empty() || t[lson].v[p1].y > t[now].v[t[now].v.size() - 1].y) { t[now].v.push_back(t[lson].v[p1]); } ++ p1; } else if(t[rson].v[p2].x >= t[lson].v[p1].x && t[rson].v[p2].y >= t[lson].v[p1].y || t[rson].v[p2].x > t[lson].v[p1].x) { if(t[now].v.empty() || t[rson].v[p2].y > t[now].v[t[now].v.size() - 1].y) { t[now].v.push_back(t[rson].v[p2]); } ++ p2; } } while(p1 < t[lson].v.size()) { if(t[now].v.empty() || (t[lson].v[p1].x <= t[now].v[siz].x && t[lson].v[p1].y > t[now].v[siz].y)) t[now].v.push_back(t[lson].v[p1]); ++p1; } while(p2 < t[rson].v.size()) { if(t[now].v.empty() || (t[rson].v[p2].x <= t[now].v[siz].x && t[rson].v[p2].y > t[now].v[siz].y)) t[now].v.push_back(t[rson].v[p2]); ++p2; } } } void build(int l, int r, int now) { if(l == r) { t[now].v.push_back(P(p[l].x, p[l].y)); return ; } int mid = (l + r) >> 1; build(l, mid, now << 1), t[now].ls = now << 1; if(r > mid) build(mid + 1, r, now << 1 | 1), t[now].rs = now << 1 | 1; pushup(l, r, now); } inline void query(int l, int r, int now, int L, int R) { if(l >= L && r <= R) { if(G.empty()) { G = t[now].v; } else { V = G, A = t[now].v; G.clear(); // merge(V, A) int p1 = 0, p2 = 0; while(p1 < V.size() && p2 < A.size()) { if(V[p1].x == A[p2].x && V[p1].y == A[p2].y) ++p1, ++p2; else if(V[p1].x >= A[p2].x && V[p1].y >= A[p2].y || V[p1].x > A[p2].x) { if(G.empty() || V[p1].y > G[G.size() - 1].y) { G.push_back(V[p1]); } ++ p1; } else if(A[p2].x >= V[p1].x && A[p2].y >= V[p1].y || A[p2].x > V[p1].x) { if(G.empty() || A[p2].y > G[G.size() - 1].y) { G.push_back(A[p2]); } ++ p2; } } while(p1 < V.size()) { if(G.empty() || (V[p1].x <= G[G.size() - 1].x && V[p1].y > G[G.size() - 1].y)) G.push_back(V[p1]); ++p1; } while(p2 < A.size()) { if(G.empty() || (A[p2].x <= G[G.size() - 1].x && A[p2].y > G[G.size() - 1].y)) G.push_back(A[p2]); ++p2; } } return; } int mid = (l + r) >> 1; if(L <= mid) query(l, mid, now << 1, L, R); if(R > mid) query(mid + 1, r, now << 1 | 1, L, R); } int main() { int i , j, q; scanf("%d" , &n); for(i = 1; i <= n ; ++i) { scanf("%lld%lld", &p[i].x, &p[i].y); } build(1, n, 1), scanf("%d", &q); for(int cas = 1; cas <= q; ++cas) { int l, r; scanf("%d%d", &l, &r); G.clear(); query(1, n, 1, l, r); ll w = 1; for(j = 0; j < G.size(); ++j) { w *= (1ll * (ll) (G[j].x ^ G[j].y)) % mod, w %= mod; } printf("%lld ", w); } return 0; }
卡常版:
#include <cstdio> #include <algorithm> #include <cstring> #include <vector> #define N 200006 #define ll long long #define mod 1000000007 #define lson t[now].ls #define rson t[now].rs #define siz (t[now].v.size() - 1) #define setIO(s) freopen(s".in", "r" , stdin) , freopen(s".out", "w", stdout) using namespace std; namespace IO { char *p1, *p2, buf[100000]; #define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ ) int rd() { int x = 0; char c = nc(); while (c < 48) { c = nc(); } while (c > 47) { x = (((x << 2) + x) << 1) + (c ^ 48), c = nc(); } return x; } char pbuf[100000],*pp=pbuf; void push(const char c) { if(pp-pbuf==100000) fwrite(pbuf,1,100000,stdout),pp=pbuf; *pp++=c; } void write(int x) { static int sta[35]; int top=0; do{sta[top++]=x%10,x/=10;}while(x); while(top) push(sta[--top]+'0'); push(' '); } } int n ; struct P { ll x , y; P(ll x = 0, ll y = 0) : x(x), y(y) {} }p[N]; struct Node { int ls, rs ; vector <P> v; }t[N << 2]; vector <P> G, V, A; inline void pushup(int L, int R, int now) { if(!rson) { t[now].v = t[lson].v; } else { int p1 = 0, p2 = 0; while(p1 < t[lson].v.size() && p2 < t[rson].v.size()) { if(t[lson].v[p1].x == t[rson].v[p2].x && t[lson].v[p1].y == t[rson].v[p2].y) ++p1, ++p2; else if(t[lson].v[p1].x >= t[rson].v[p2].x && t[lson].v[p1].y >= t[rson].v[p2].y || t[lson].v[p1].x > t[rson].v[p2].x) { if(t[now].v.empty() || t[lson].v[p1].y > t[now].v[t[now].v.size() - 1].y) { t[now].v.push_back(t[lson].v[p1]); } ++ p1; } else if(t[rson].v[p2].x >= t[lson].v[p1].x && t[rson].v[p2].y >= t[lson].v[p1].y || t[rson].v[p2].x > t[lson].v[p1].x) { if(t[now].v.empty() || t[rson].v[p2].y > t[now].v[t[now].v.size() - 1].y) { t[now].v.push_back(t[rson].v[p2]); } ++ p2; } } while(p1 < t[lson].v.size()) { if(t[now].v.empty() || (t[lson].v[p1].x <= t[now].v[siz].x && t[lson].v[p1].y > t[now].v[siz].y)) t[now].v.push_back(t[lson].v[p1]); ++p1; } while(p2 < t[rson].v.size()) { if(t[now].v.empty() || (t[rson].v[p2].x <= t[now].v[siz].x && t[rson].v[p2].y > t[now].v[siz].y)) t[now].v.push_back(t[rson].v[p2]); ++p2; } } } void build(int l, int r, int now) { if(l == r) { t[now].v.push_back(P(p[l].x, p[l].y)); return ; } int mid = (l + r) >> 1; build(l, mid, now << 1), t[now].ls = now << 1; if(r > mid) build(mid + 1, r, now << 1 | 1), t[now].rs = now << 1 | 1; pushup(l, r, now); } inline void query(int l, int r, int now, int L, int R) { if(l >= L && r <= R) { if(G.empty()) { G = t[now].v; } else { V = G, A = t[now].v; G.clear(); // merge(V, A) int p1 = 0, p2 = 0; while(p1 < V.size() && p2 < A.size()) { if(V[p1].x == A[p2].x && V[p1].y == A[p2].y) ++p1, ++p2; else if(V[p1].x >= A[p2].x && V[p1].y >= A[p2].y || V[p1].x > A[p2].x) { if(G.empty() || V[p1].y > G[G.size() - 1].y) { G.push_back(V[p1]); } ++ p1; } else if(A[p2].x >= V[p1].x && A[p2].y >= V[p1].y || A[p2].x > V[p1].x) { if(G.empty() || A[p2].y > G[G.size() - 1].y) { G.push_back(A[p2]); } ++ p2; } } while(p1 < V.size()) { if(G.empty() || (V[p1].x <= G[G.size() - 1].x && V[p1].y > G[G.size() - 1].y)) G.push_back(V[p1]); ++p1; } while(p2 < A.size()) { if(G.empty() || (A[p2].x <= G[G.size() - 1].x && A[p2].y > G[G.size() - 1].y)) G.push_back(A[p2]); ++p2; } } return; } int mid = (l + r) >> 1; if(L <= mid) query(l, mid, now << 1, L, R); if(R > mid) query(mid + 1, r, now << 1 | 1, L, R); } int main() { // setIO("input"); using namespace IO; int i , j, q; n = rd(); for(i = 1; i <= n ; ++i) { p[i].x = (ll) rd(); p[i].y = (ll) rd(); } build(1, n, 1); q = (ll) rd(); for(int cas = 1; cas <= q; ++cas) { int l, r; l = rd(), r = rd(); G.clear(); query(1, n, 1, l, r); ll w = 1; for(j = 0; j < G.size(); ++j) { w *= (1ll * (ll) (G[j].x ^ G[j].y)) % mod, w %= mod; } write(w); } fwrite(pbuf,1,pp-pbuf,stdout); return 0; }