Codeforces Round 904 (Div. 2)

https://codeforces.com/contest/1884

A.

没想到是暴力,做的很晚

B.

手玩一下即可

C. Medium Design

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

\(Solution\)

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

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

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

对于线段 \(l_i,r_i\) 的处理,采用离散化即可.

点击查看代码
#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 @ 2023-10-26 15:06  LZH_03  阅读(28)  评论(0编辑  收藏  举报