Codeforces Round 904 (Div. 2)

https://codeforces.com/contest/1884

A.

没想到是暴力,做的很晚

B.

手玩一下即可

C. Medium Design

给定一个长为 n 的数组 a ,和若干条线段 [li,ri] ,你可以选择这其中的任何若干条线段,并让 alar+1.请你计算可以得到的 max(a)min(a) .

Solution

这题本来想的是先把所有的加进去,得到最大值后删去不包含最大值的线段,但是可能有多个最大值,这就很难搞了.

我们找 1m 中任意一点 x ,假如这个点是要求的最大值的点,那么删去其他不包含该点的点不影响结果,所以我们可以只考虑包含了这个点的线段,一定有 aia1,i[1,x] , 并有 aiam,i[x+1,m] ,那么答案一定是 max(axa1,axam) ,但是注意,这时候的 a1,am 显然是删去了我们前面说的那些不必要的边后的 a1,am ,如果对每一个 x 我们都判断一遍线段,刨除不包含 ax 的线段,那会使得时间复杂度达到 O(n2) ,这是显然不可行的.

可以提前把所有的 a1,am 上的边删掉,删掉了包含 a1 且不包含 ax 的边,同时包含 a1ax 的边被删掉,a1,ax 同时减小,并不会影响答案.此时最小值变成了 0 ,答案就是 max(ai) .注意 a1am 上的边应该分开删除,否则如果 a1,am 都包含了 ax 会使得答案变小了.

对于线段 li,ri 的处理,采用离散化即可.

点击查看代码
#include<bits/stdc++.h>
#define l first
#define r second
using namespace std;
const int N = 1e5+10;
#define int long long
pair<int,int> p[N];
int a[2*N];
int idx = 0;
vector<int> mp; // 存储所有待离散化的值


// 二分求出x对应的离散化的值
int find(int x) // 找到第一个大于等于x的位置
{
    int l = 0, r = mp.size() - 1;
    while (l < r)
    {
        int mid = l + r >> 1;
        if (mp[mid] >= x) r = mid;
        else l = mid + 1;
    }
    return r + 1; // 映射到1, 2, ...n
}
void solve()
{
    memset(a,0,sizeof a);
    mp.clear();
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int l,r;
        cin>>l>>r;
        mp.push_back(l);
        mp.push_back(r);

        p[i].l = l;
        p[i].r = r;
    }
    sort(mp.begin(), mp.end()); // 将所有值排序
    mp.erase(unique(mp.begin(), mp.end()), mp.end());   // 去掉重复元素


    for(int i=1;i<=n;i++)
    {
        if(p[i].l==1)continue;

        int l = find(p[i].l),r = find(p[i].r);
        a[l]+=1,a[r+1]-=1;
    }
    int ans_max = 0;
    int t = 0;
    for(int i=1;i<=mp.size()+1;i++)
    {
        t+=a[i];
        ans_max = max(ans_max,t);
    }

    memset(a,0,sizeof a);
    for(int i=1;i<=n;i++)
    {
        if(p[i].r==m)continue;

        int l = find(p[i].l),r = find(p[i].r);
        a[l]+=1,a[r+1]-=1;
    }
    int ans_max_2 = 0;
    t = 0;
    for(int i=1;i<=mp.size()+1;i++)
    {
        t+=a[i];
        ans_max_2 = max(ans_max_2,t);
    }
    int ans = max(ans_max,ans_max_2);
    cout<<ans<<endl;
}


signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int T;
    cin>>T;
    while(T--)
        solve();

    return 0;
}


如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
posted @   Rainy_L  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示