题解:P10764 [BalticOI 2024] Wall
Claire0918 · · 题解
考虑分别求
我们注意到
如果存在
如果不存在满足上文条件的
观察形式,综上,我们得出结论:
- 无论何时,
i 总有贡献2^n 。 - 如果不存在
j \leq i 使得a_j \geq x, b_j \geq x ,那么额外贡献-2^{n - s_i} 。 - 如果不存在
j \geq i 满足该条件,额外贡献-2^{n - (s_n - s_{i - 1})} 。 - 特别地,如果 2 和 3 同时满足,额外贡献
2^{n - s_n} 。
直接使用线段树维护
我们考虑对于线段树上一个节点 pushup 中将左儿子的贡献乘到右儿子上合并,于是我们可以对叶节点记
这样我们只需要修改
Code:
#include<bits/stdc++.h>
#define mem(a, v) memset(a, v, sizeof(a))
using namespace std;
const int maxn = 5e5 + 10, mod = 1e9 + 7;
int n, res = 0;
int a[maxn], b[maxn], pwr[maxn], val[maxn];
vector<int> tmp, ad[maxn << 1];
template<typename Tp_x, typename Tp_y>
inline int mod_add(Tp_x x, Tp_y y){
return x += y, x >= mod ? x -= mod : x;
}
template<typename Tp_x, typename Tp_y>
inline int self_mod_add(Tp_x &x, Tp_y y){
return x = mod_add(x, y);
}
template<typename Tp, typename... Arg>
inline int mod_add(Tp x, Arg ...args){
return x += mod_add(args...), x >= mod ? x -= mod : x;
}
namespace segtree{
struct{
int l, r, pre, suf, val;
} tree[maxn << 2];
inline void pushup(int index){
tree[index].pre = mod_add(tree[index << 1].pre, (long long)tree[index << 1 | 1].pre * tree[index << 1].val % mod);
tree[index].suf = mod_add(tree[index << 1 | 1].suf, (long long)tree[index << 1].suf * tree[index << 1 | 1].val % mod);
tree[index].val = (long long)tree[index << 1].val * tree[index << 1 | 1].val % mod;
}
inline void build(int index, int l, int r){
tree[index].l = l, tree[index].r = r;
if (l == r){
return;
}
const int mid = l + r >> 1;
build(index << 1, l, mid), build(index << 1 | 1, mid + 1, r);
}
inline void modify(int index, int x, int k){
if (tree[index].l == tree[index].r){
return tree[index].pre = (long long)pwr[n - x] * k % mod, tree[index].suf = (long long)pwr[x - 1] * k % mod, tree[index].val = k, void();
}
const int mid = tree[index].l + tree[index].r >> 1;
modify(index << 1 | x > mid, x, k), pushup(index);
}
}
using namespace segtree;
inline int pos(int x){
return lower_bound(tmp.begin(), tmp.end(), x) - tmp.begin() + 1;
}
int main(){
scanf("%d", &n), build(1, 1, n), pwr[0] = 1;
for (int i = 1; i <= n; i++){
scanf("%d", &a[i]), tmp.push_back(a[i]), pwr[i] = (pwr[i - 1] << 1) % mod;
}
for (int i = 1; i <= n; i++){
scanf("%d", &b[i]), tmp.push_back(b[i]);
self_mod_add(res, mod - (long long)pwr[n - 1] * mod_add(a[i], b[i]) % mod);
}
sort(tmp.begin(), tmp.end()), tmp.erase(unique(tmp.begin(), tmp.end()), tmp.end()), self_mod_add(res, (long long)tmp[0] * n % mod * pwr[n] % mod);
for (int i = 1; i <= n; i++){
ad[pos(a[i])].push_back(i), ad[pos(b[i])].push_back(i);
}
for (int i = 2; i <= tmp.size(); i++){
for (auto x: ad[i - 1]){
modify(1, x, ++val[x]);
}
self_mod_add(res, (long long)(tmp[i - 1] - tmp[i - 2]) * mod_add((long long)n * pwr[n] % mod, mod - tree[1].pre, mod - tree[1].suf, (long long)n * tree[1].val % mod) % mod);
}
printf("%d", res);
return 0;
}