线段与区间

线段与区间

总结

一种经典的题型,诸如区间合并,区间选择等

区间合并

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
vector<PII> q;
for(int i=1;i<=n;i++){
    cin>>a[i]>>b[i];
    mx=max({mx,a[i],b[i]});
    if(a[i]>=b[i]){
        mn=min(mn,b[i]);
        q.pb({b[i],a[i]});
    }
}
sort(all(q));
vector<PII> s;
for(auto [l,r] : q){
    if(!s.empty()&&l<=s.back()[1]){
        s.back()[1]=max(s.back()[1],r);
    }else{
        s.push_back({l,r});
    }
}

智乃的k线段区间

地址

先预处理出所有“包含K条线段”的最小区间

利用 map 对 key 的排序使右端点有序,再分别把 l 放入 multiset 使左端点有序

保证 multiset 的大小为 k,此时的左右端点即为最小区间

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void solve()
{
    int n,m,k;
    cin>>n>>m>>k;
    map<int,vector<int>> mp;
    for(int i=1;i<=n;i++){
        int l,r;
        cin>>l>>r;
        mp[r].push_back(l);
    }
    multiset<int> s;
    ll ans=0;
    int left=1;
    for(auto [r,v] : mp){
        for(auto l:v){
            s.insert(l);
        }
        while(s.size()>k){
            s.erase(s.begin());
        }
        if(s.size()==k){
            int tp=*s.begin();
            ans+=(tp-left+1)*(m-r+1);
            left=tp+1;
        }
    }
    cout<<ans<<'\n';
}
Licensed under CC BY-NC-SA 4.0
最后更新于 Apr 27, 2024 00:00 UTC
本博客已稳定运行
使用 Hugo 构建
主题 StackJimmy 设计