2016 多校第 2 场
Jul 22, 2016 • 🍻 02min 36s read
🔖 acm训练赛数据结构解题报告
1004 Differencia
¶题目描述
¶有两个序列:
有两种操作:
: 将所有的 置为 : 询问 中有多少个 满足
数据范围:
次询问,强制在线。
题目简析
¶将
如果预处理初每个节点所维护的区间中每个节点在左右子节点中的
程序实现
¶1004.cpp | 153 lines.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153#include <algorithm>#include <cstdio>#include <cstring>#include <iostream>
inline int read() { bool positive = true; char c = getchar(); int s = 0; for (; c < '0' || c > '9'; c = getchar()) if (c == '-') positive = false; for (; c >= '0' && c <= '9'; c = getchar()) s = s * 10 + c - '0'; return positive ? s : -s;}
namespace solve { const int MAXN = 100000 + 10; int A[MAXN], B[20][MAXN], L[20][MAXN], R[20][MAXN]; int sumv[MAXN << 2], setv[MAXN << 2], posv[MAXN << 2];
inline void build(int o, int lft, int rht, int cur = 0) { setv[o] = 0; if (lft == rht) { B[cur][lft] = read(); sumv[o] = A[lft] >= B[cur][lft] ? 1 : 0; } else { int mid = lft + rht >> 1; build(o << 1, lft, mid, cur + 1); build(o << 1 | 1, mid + 1, rht, cur + 1);
int tot = lft, i = lft, j = mid + 1; for (; i <= mid && j <= rht;) if (B[cur + 1][i] <= B[cur + 1][j]) B[cur][tot++] = B[cur + 1][i++]; else B[cur][tot++] = B[cur + 1][j++]; for (; i <= mid;) B[cur][tot++] = B[cur + 1][i++]; for (; j <= rht;) B[cur][tot++] = B[cur + 1][j++]; sumv[o] = sumv[o << 1] + sumv[o << 1 | 1];
// 计算区间 [lft,rht] 的每个节点在左右子节点中的 rank L[cur][lft] = lft; R[cur][lft] = mid + 1; for (int& l = L[cur][lft]; l <= mid && B[cur + 1][l] <= B[cur][lft]; ++l) ; for (int& r = R[cur][lft]; r <= rht && B[cur + 1][r] <= B[cur][lft]; ++r) ; --L[cur][lft]; --R[cur][lft]; for (int i = lft + 1; i <= rht; ++i) { L[cur][i] = L[cur][i - 1] + 1; R[cur][i] = R[cur][i - 1] + 1; for (int& l = L[cur][i]; l <= mid && B[cur + 1][l] <= B[cur][i]; ++l) ; for (int& r = R[cur][i]; r <= rht && B[cur + 1][r] <= B[cur][i]; ++r) ; --L[cur][i]; --R[cur][i]; } } }
inline void pushdown(int o, int lft, int rht, int cur) { int lc = o << 1, rc = o << 1 | 1, mid = lft + rht >> 1; setv[lc] = setv[o]; posv[lc] = posv[o] >= lft ? L[cur][posv[o]] : lft - 1; setv[rc] = setv[o]; posv[rc] = posv[o] >= lft ? R[cur][posv[o]] : mid; sumv[lc] = posv[lc] - lft + 1; sumv[rc] = posv[rc] - mid; setv[o] = 0; }
int ul, ur, uv; inline void update(int o, int lft, int rht, int pos, int cur = 0) { if (lft == rht) { sumv[o] = uv >= B[cur][lft] ? 1 : 0; return; } if (ul <= lft && rht <= ur) { int mid = lft + rht >> 1; setv[o] = uv; posv[o] = pos; sumv[o] = pos - lft + 1; } else { if (setv[o]) pushdown(o, lft, rht, cur); int mid = lft + rht >> 1; if (ul <= mid) update(o << 1, lft, mid, pos >= lft ? L[cur][pos] : lft - 1, cur + 1); if (mid < ur) update(o << 1 | 1, mid + 1, rht, pos >= lft ? R[cur][pos] : mid, cur + 1); sumv[o] = sumv[o << 1] + sumv[o << 1 | 1]; } }
int ql, qr; inline int query(int o, int lft, int rht, int cur = 0) { if (ql <= lft && rht <= qr) return sumv[o]; if (setv[o]) pushdown(o, lft, rht, cur); int mid = lft + rht >> 1; int ans = 0; if (ql <= mid) ans += query(o << 1, lft, mid, cur + 1); if (mid < qr) ans += query(o << 1 | 1, mid + 1, rht, cur + 1); return ans; }}; // namespace solve
typedef long long LL;const int MOD = 1000000000 + 7;const int C = ~(1 << 31);const int M = (1 << 16) - 1;
int n, m, A, B, a, b, last;
inline int rnd(int last) { a = (36969 + (last >> 3)) * (a & M) + (a >> 16); b = (18000 + (last >> 3)) * (b & M) + (b >> 16); return (C & ((a << 16) + b)) % 1000000000;}
int main() { int T_T = read(); for (int kase = 1; kase <= T_T; ++kase) { scanf("%d%d%d%d", &n, &m, &A, &B); for (int i = 1; i <= n; ++i) solve::A[i] = read(); solve::build(1, 1, n);
LL ans = 0LL; a = A, b = B, last = 0; for (int i = 1; i <= m; ++i) { int l = rnd(last) % n + 1; int r = rnd(last) % n + 1; int x = rnd(last) + 1; if (l > r) std::swap(l, r); if ((l + r + x) & 1) { solve::ul = l; solve::ur = r; solve::uv = x; int pos = std::upper_bound(solve::B[0] + 1, solve::B[0] + n + 1, x) - solve::B[0] - 1; solve::update(1, 1, n, pos); } else { solve::ql = l; solve::qr = r; last = solve::query(1, 1, n); ans = (ans + (LL)i * last) % MOD; } } printf("%d\n", ans); }
return 0;}