西交2021校赛 J题校赛质量

彩彩在视频网站上拥有N个粉丝,并且发布了M个视频,编号为0,1,…,M-1 。粉丝会为编号连续的视频点赞,其中第 i 个粉丝选择为 (表示大于等于 并且严格小于 的整数范围)的视频点赞。该网站对视频质量有两个评价指标 x和 y 分别表示:

最小的整数 ,x表示从作者的N个粉丝中 可以选出 x 个粉丝,使得全部的视频都被选中的粉丝点赞过;
最小的整数 ,表示从作者的N个粉丝中 任意选出y 个粉丝,使得全部的视频都被选中的粉丝点赞过。
现在彩彩想要计算 x 和 y,以此来判断自己的视频质量。可是彩彩不会算,因此把任务交给了作为彩黑警察的你。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题目传送门

解题思路:
x: 用贪心思想,从0开始每次选取区间跨度最大的,那么得到的区间总数就是x
y: 鸽巢原理,如果有一个视频只有一个粉丝点赞,那么y就等于n,实际上就是求所有视频中,其被多少个区间覆盖,这个可以根据t1-t2得到。统计最小的(t1-t2),记为p。然后答案就是n+1-p;
int t1 = upper_bound(a.begin(),a.end(),c[i])-a.begin();
int t2 = lower_bound(b.begin(),b.end(),c[i])-b.begin();
易错点,由于M的值特别大,超出了1e9,所以不能遍历所有视频,可以只选区间的左右端点去遍历,但是这时候又会遇到一种情况,如图下所示。s5端内的视频就不会遍历到了,解决办法是加上区间左右端点再扩充一个视频就好了。
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node{
    ll l,r;
    node(ll a,ll b):l(a),r(b){}
};
bool compare(node n1,node n2){
    if(n1.l == n2.l){
        return n1.r < n2.r;
    }
    return n1.l < n2.l;
}



int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("in1.txt", "r", stdin);
    int n;
    ll m;
    cin>>n>>m;
    vector<node>v;
    vector<ll>a,b,c,d;
    for(int i = 0;i<n;i++){
        ll l,r;
        cin>>l>>r;
        a.push_back(l);
        b.push_back(r-1);
        c.push_back(l);
        c.push_back(r-1);
        if(l>0){
            c.push_back(l-1);
        }
        if(r<m){
            c.push_back(r);
        }
        v.push_back(node(l,r));
    }
    sort(a.begin(),a.end());
    sort(b.begin(),b.end());
    sort(v.begin(),v.end(),compare);
    int res = 1;
    ll cur_l = 0,cur_r = -1;
    int i = 0;
    while(i<n && v[i].l == cur_l){
        cur_r = max(cur_r,v[i].r);
        i++;
    }
    for(int j = i;j<n && cur_r!=m;j++){
        if(v[j].l<=cur_r && v[j].r > cur_r){
            res++;
            ll tmp_r = cur_r;
            while(j<n && v[j].l <= tmp_r){
                cur_r = max(cur_r,v[j].r);
                j++;
            }
            j--;
        }
    }
    int x = res;
    res = 2e5+3;
    for(i = 0;i<c.size();i++){
        int t1 = upper_bound(a.begin(),a.end(),c[i])-a.begin();
        int t2 = lower_bound(b.begin(),b.end(),c[i])-b.begin();
        res = min(res,t1-t2);
    }
    int y = n+1-res;
    cout<<x<<" "<<y;
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值