P11843 Sol
HDS_Acenaphthylene · · 题解
首先,离散化然后把
cin >> _n >> m >> q;
rep(i, 1, m)
cin >> ml[i] >> mr[i],
T[++n] = ml[i],
T[++n] = mr[i] + 1;
rep(i, 1, q)
cin >> ql[i] >> qr[i] >> k[i],
T[++n] = ql[i], T[++n] = qr[i] + 1;
std::sort(T + 1, T + 1 + n);
n = std::unique(T + 1, T + 1 + n) - T - 1;
# define F(i) (std::lower_bound(T + 1, T + 1 + n, i) - T)
T[n + 1] = _n + 1;
rep(i, 1, m){
ml[i] = F(ml[i]);mr[i] = F(mr[i] + 1) - 1;
tag[ml[i]] ^= 1;tag[mr[i] + 1] ^= 1;}
rep(i, 1, n) tag[i] ^= tag[i - 1];
考虑如何求答案。注意到一个区间的答案一定形如
即先满足有足够多的
这里有一个关键的性质:前面的
我们考虑二分一个分界点,使其满足在
得到分界点后,答案的串为前面部分的
至于此处为什么从后面开始取,由于我们的取法,每个
然后有哈希把答案预处理就好了。
# include<bits/stdc++.h>
# define rep(i,a,b) for(int i = (a);i <= (b);i ++)
# define dwn(i,a,b) for(int i = (a);i >= (b);i --)
# define fid(i,a,F) for(int i = (a);F;i ++)
# define int32 int
# define int64 long long
# define int16 short
# define dbg(x) std::cerr << #x << ":" << x <<"\n"
# define FaILurEg(s) std::freopen(s".in","r", stdin);std::freopen(s".out","w",stdout);
# define ___main signed main()
# define int long long
using std::cin;using std::cout;
int _n, n, m, q;
int ml[200005], mr[200005], ql[200005], qr[200005], k[200005];
int T[800005], tag[800006], c1[800005], c2[800005];int64 b[800005];
template<int mod>
inline int64 qpow(int64 x, int64 y) {
//assert(y >= 0);
if(y == 0) return 1;
if(y == 1) return x % mod;
int64 m = qpow<mod>(x, y >> 1);
return m * m % mod * (y & 1 ? x : 1) % mod;
}
___main {//FaILurEg("bestsub");
const int mod = 1000000007;
std::ios::sync_with_stdio(0);cin.tie(0);
cin >> _n >> m >> q;
rep(i, 1, m) cin >> ml[i] >> mr[i], T[++n] = ml[i], T[++n] = mr[i] + 1;
rep(i, 1, q) cin >> ql[i] >> qr[i] >> k[i], T[++n] = ql[i], T[++n] = qr[i] + 1; std::sort(T + 1, T + 1 + n);n = std::unique(T + 1, T + 1 + n) - T - 1;
# define F(i) (std::lower_bound(T + 1, T + 1 + n, i) - T)
T[n + 1] = _n + 1;
rep(i, 1, m){
ml[i] = F(ml[i]);mr[i] = F(mr[i] + 1) - 1;
tag[ml[i]] ^= 1;tag[mr[i] + 1] ^= 1;}
rep(i, 1, n) tag[i] ^= tag[i - 1],
c1[i] = c1[i - 1] + tag[i] * (T[i + 1] - T[i]),
c2[i] = c2[i - 1] + (T[i + 1] - T[i])
//,assert(T[i + 1] - T[i]?1:(std::cerr << T[i] << " " << T[i + 1] << "\n" ,0))
,b[i] = b[i - 1] * qpow<mod>(2, T[i + 1] - T[i]) + tag[i] * (qpow<mod>(2, T[i + 1] - T[i]) + mod - 1) % mod, b[i] %= mod
;
rep(i, 1, q) {
ql[i] = F(ql[i]);qr[i] = F(qr[i] + 1) - 1;
int l = ql[i] - 1, r = qr[i], ans = 0;
if(c1[qr[i]] - c1[ql[i] - 1] >= k[i]) {
cout << (qpow<mod>(2, k[i]) + mod - 1) % mod << "\n";continue;
}
while(l <= r) {
int mid = (l + r) >> 1;
//check
bool F = (c2[qr[i]] - c2[mid] < k[i] - (c1[mid] - c1[ql[i] - 1]));
if(!F) ans = std::max(ans, mid), l = mid + 1;
else r = mid - 1;
}
int R = k[i] - (c1[ans] - c1[ql[i] - 1]);
//std::cerr<<"Q" << ql[i] << " " << qr[i] << " " << ans << "\n";
assert(!tag[ans + 1]);
int64 out = (qpow<mod>(2, c1[ans] - c1[ql[i] - 1]) + mod - 1) % mod,
out2 = (b[qr[i]] - b[ans] * qpow<mod>(2, T[qr[i] + 1] - T[ans + 1]) % mod + mod) % mod;
0;
//std::cerr << b[ans] - b[ql[i] - 1] * qpow<mod>(2, T[ans + 1] - T[ql[i]]) << "\n";
//rep(j, ans + 2, qr[i])
// out2 = out2 * qpow<mod>(2, T[j + 1] - T[j]) + tag[j] * (qpow<mod>(2, T[j + 1] - T[j]) + mod - 1) % mod, out2 %= mod;
cout << (out * qpow<mod>(2, R) + out2) % mod << "\n";
}
}