Loading

题解: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,你谷机子太慢了。

posted @ 2026-02-28 08:48  GE9x  阅读(47)  评论(1)    收藏  举报