1 条题解
-
0
思路与算法
按距离D排序。对区间维护生成多项式Π(1+V_i z)的0至6阶系数及最小V,线段树合并为截断卷积。查询得到区间多项式后,用b_0=1、b_j=a_j-minV·b_{j-1}逐项除掉最小项的因子,最后输出K!b_K模2^32。
正确性说明
多项式K阶系数把每个K元素子集的乘积恰计一次;样本顺序不同属于不同方案,所以乘K阶乘。最小V全局唯一,除去其因子精确排除仪器不选的区域。低阶系数只依赖低阶输入,截断卷积与递推除法不影响所求阶数。
复杂度
设最大阶B=6,排序O(nlogn),建树及初始化O(B²n),每查询O(B²logn+B),总O(nlogn+B²n+qB²logn),空间O(Bn)。
易错点
区间只有K个或更少区域时,删最小后不足K,直接0。模2^32为合数,不使用除法或逆元;uint32截断与uint64无符号乘加的低32位恰等价所需取模。距离和值互异均按原题保证。
参考代码(C++11)
#include <bits/stdc++.h> using namespace std; struct V { array<uint32_t, 7> p{}; uint32_t mn = UINT32_MAX; V() { p[0] = 1; } }; V mergeV(const V &a, const V &b) { V z; z.mn = min(a.mn, b.mn); for (int i = 1; i <= 6; i++) { uint64_t s = 0; for (int j = 0; j <= i; j++) s += uint64_t(a.p[j]) * b.p[i - j]; z.p[i] = s; } return z; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, q; cin >> n >> q; vector<int> d(n); for (int &x : d) cin >> x; vector<pair<int, uint32_t>> a(n); for (int i = 0; i < n; i++) { uint32_t v; cin >> v; a[i] = {d[i], v}; } sort(a.begin(), a.end()); int S = 1; while (S < n) S *= 2; vector<V> tr(2 * S); for (int i = 0; i < n; i++) { d[i] = a[i].first; tr[S + i].p[1] = tr[S + i].mn = a[i].second; } for (int i = S - 1; i; i--) tr[i] = mergeV(tr[2 * i], tr[2 * i + 1]); while (q--) { int L, R, K; cin >> L >> R >> K; int l = lower_bound(d.begin(), d.end(), L) - d.begin(), r = upper_bound(d.begin(), d.end(), R) - d.begin(); if (r - l <= K) { cout << 0 << '\n'; continue; } V z; for (l += S, r += S; l < r; l /= 2, r /= 2) { if (l & 1) z = mergeV(z, tr[l++]); if (r & 1) z = mergeV(z, tr[--r]); } uint32_t b = 1; for (int i = 1; i <= K; i++) b = z.p[i] - uint32_t(uint64_t(z.mn) * b); for (int i = 2; i <= K; i++) b = uint64_t(b) * i; cout << b << '\n'; } }
- 1