*题解:P11800 【MX-X9-T4】『GROI-R3』区间
解析
题意等价于问有多少个位置 \(k\),使得其对于所有 \(1 \le i \le n\),右移 \(a_i\) 后不属于任何一个区间。
发现有一个区间长度互不相等的限制,不知道有什么用。
发现 \(a_i \le 5 \times 10 ^ 5\),但是区间和 \(k\) 的值域非常大。
先对 \(a\) 从小到大排序。
若对于一个 \(x\),有 \(x + a_{n} = l_j\)。那么对于所有 \(y \in [x,x + r_j - l_j]\),都有 \(y + a_{n} \in [l_j,r_j]\)。由于 \(a\) 的值域很小,感性理解,对于 \(x' + a_{n - 1} = l_j\),\([x',x' + len_j]\) 很有可能跟 \([x,x + len_j]\) 有交。事实上,若 \(a_n - a_{n - 1} \le len_j\),则两区间有交。
也就是说,对于一个区间 \([l_i,r_i]\),可以将 \(a\) 分成 \(\frac{a_{max}}{len_i}\) 份,每段 \(a\) 可以并出一段连续的值域段。这样,根据调和级数的结论,所有 \(m\) 个区间会产生 \(O(a \log m)\) 个值域段,排序后再进行合并就可以得出非法值域段的并,总时间复杂度 \(O(a \log m \log m)\)。
代码
/*
*/
#include<bits/stdc++.h>
#define eps 0.000001
#define mid ((l + r) >> 1)
#define ls(x) ((x) << 1)
#define rs(x) (((x) << 1) | 1)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<ll,ll> pii;
const int N = 5e5 + 5,M = 2e5 + 5,base = 13331,mod = 998244353;
int a[N];
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
ll n,m,v;
cin>>n>>m>>v;
vector<int> vec;
for(int i=1;i<=n;i++){
cin>>a[i];
vec.push_back(a[i]);
}
sort(vec.begin(),vec.end(),greater<int>());
vector<pii> seg;
for(int i=1;i<=m;i++){
ll l,r;
cin>>l>>r;
int now = 0,t = 0;
while(now < vec.size()){
t = upper_bound(vec.begin() + now,vec.end(),vec[now] - (r - l + 1),greater<ll>()) - vec.begin() - 1;
// cerr<<now<<" "<<t<<" "<<vec[now]<<" "<<vec[t]<<" "<<l<<" "<<r<<'\n';
seg.push_back({max(1ll,l - vec[now]),max(0ll,min(v,r - vec[t]))});
now = t + 1;
}
}
sort(seg.begin(),seg.end());
seg.push_back({9e18,9e18});
ll l = 0,r = -1,res = v;
for(int i=0;i<seg.size();i++){
// cout<<seg[i].first<<" "<<seg[i].second<<'\n';
if(seg[i].first > r){
// cout<<"!!! "<<l<<" "<<r<<'\n';
res -= r - l + 1;
if(seg[i].first > v) break;
l = seg[i].first,r = seg[i].second;
}else{
r = max(r,seg[i].second);
}
}
cout<<res;
return 0;
}
/*
*/

浙公网安备 33010602011771号