题解:P11830 [省选联考 2025] 幸运数字
感觉想得不是很顺,加训。
P11830
考虑枚举每一个数 \(x\) 能否满足条件。但是发现何意味出题人给的 \(l\),\(r\) 是 \(10^9\) 量级的,还得离散化。于是考虑将每一个点和两点之间的间隔看做一个点,这样每一个点带一个权值(也就是对应的区间长度)\(c\),这个可以差分处理。如果这个点可以被作为中位数,总答案 \(+c\) 就行。
然后对于每一个 \(x\),考虑将所有值域覆盖 \(x\) 的二元组全部设置成 \(x\) 并且长度开到最大,这个是显然的。那么现在只剩下那些必定小于 \(<x\),和必定 \(>x\) 的二元组。我们把这两种数分别视作两个大的二元组,长度上下界就是所有加起来。考虑现在已知的信息:\(x\) 的个数,\(>x\) 和 \(<x\) 的取值范围。这个时候可以直接列不等式看一下有没有解就行了,时间是常数。
那么刚刚提到的东西都可以直接前缀和预处理,离散化是瓶颈,时间 \(n \log n\)。
//to kill a living book
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+7,M=(N<<2);
int n,la[N],ra[N],lb[N],rb[N],m,c[M],cnt[M],pmx[M],pmn[M],nmx[M],nmn[M];
void solve(){
cin>>n; m=0;
for(int i=1;i<=n;i++) cin>>la[i]>>ra[i]>>lb[i]>>rb[i];
vector<int> v; for(int i=1;i<=n;i++) v.emplace_back(lb[i]),v.emplace_back(rb[i]);
sort(v.begin(),v.end()); unique(v.begin(),v.end()); map<int,int> mp;
for(int i=0;i<v.size();i++){
mp[v[i]]=++m,c[m]=1;
if(i+1<v.size()) c[++m]=v[i+1]-v[i]-1;
}
for(int i=0;i<=m+1;i++) cnt[i]=pmx[i]=pmn[i]=nmx[i]=nmn[i]=0;
for(int i=1;i<=n;i++){
lb[i]=mp[lb[i]],rb[i]=mp[rb[i]],cnt[lb[i]]+=ra[i],cnt[rb[i]+1]-=ra[i];
pmx[rb[i]]+=ra[i],pmn[rb[i]]+=la[i];
nmx[lb[i]]+=ra[i],nmn[lb[i]]+=la[i];
}
for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];
for(int i=1;i<=m;i++) pmx[i]+=pmx[i-1],pmn[i]+=pmn[i-1];
for(int i=m;i>=1;i--) nmx[i]+=nmx[i+1],nmn[i]+=nmn[i+1];
int ans=0;
for(int i=1;i<=m;i++){
if(!cnt[i]) continue;
int lmn=pmn[i-1],lmx=pmx[i-1],rmn=nmn[i+1],rmx=nmx[i+1],mid=cnt[i];
/*
l+1<=mid+r,l+mid>=r
<=> lmn+1-mid<=r<=lmx+mid
条件 <=> max(rmn,lmn+1-mid)<=min(rmx,lmx+mid)
*/
ans+=(max(rmn,lmn+1-mid)<=min(rmx,lmx+mid))*c[i];
}
cout<<ans<<"\n";
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int c,t; cin>>c>>t;
while(t--) solve();
return 0;
}
最大点 925ms,你谷机子太慢了。
本文来自博客园,作者:GE9x,转载请注明原文链接:https://www.cnblogs.com/GE9X/p/19649607

浙公网安备 33010602011771号