Charging

https://ac.nowcoder.com/acm/contest/13175/C

数轴上有[1,n]一共n个点,m个区间分别是[li,ri]。
tot为所选取的区间数量,x为所有所选取的区间的交集长度。
min(tot,x)的最大值。

 

尺取法

题意即是尽可能多的段同时重复段尽量长

所选的区间左端点一定是某区间的左端点

所取的区间右端点也是

先按左端点排序区间,让所选的个数小于等于交集的长度,

如果大了就去掉最前面的区间

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 3e5 + 7;
pair<int,int> a[N];
int n,m;
int main() {
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i)
        scanf("%d%d",&a[i].first,&a[i].second);
    sort(a+1,a+1+m);
    ll ans=0,cnt=0;
    priority_queue<int, vector<int>, greater<int> > q;
    for(int i=1;i<=m;++i){
        q.push(a[i].second);
        ++cnt;
        while(cnt>q.top()-a[i].first+1){
            q.pop();
            --cnt;
        }
        ans=max(ans,cnt);
       // cout<<"==="<<cnt<<"\n";
    }
    cout<<ans<<"\n";
    return 0;
}

 

 

二分答案

nlognlogn+mlogm

#include <bits/stdc++.h>
#define sc(x) scanf("%d", &(x))
#define pr(x) printf("%d\n", (x))
using namespace std;
typedef pair<int, int> pii;
const int N = 3e5 + 7;
#define lowbit(x) ((x) & (-x))
int tree[N];
inline void add(int i) {
    for (int pos = i; pos < N; pos += lowbit(pos)) ++tree[pos];
}
inline int query(int n) {
    int ans = 0;
    for (int pos = n; pos; pos -= lowbit(pos)) ans += tree[pos];
    return ans;
}
pii a[N];
int main() {
    int n, m;
    sc(n), sc(m);
    for (int i = 0; i < m; ++i) sc(a[i].first), sc(a[i].second);
    sort(a, a + m);
    int ans = 0;
    for (int L = 1, p = 0; L <= n; ++L) {
        while (p < m && a[p].first <= L) add(a[p++].second);
        int left = L, right = n, R = 0;
        while (left <= right) {
            int mid = left + right >> 1;//选取区间的右端点 
            int tot = p - query(mid - 1);//减去不满足我们枚举出的交集的点 
            if (tot >= mid - L + 1)//尝试扩大区间 
                left = mid + 1, R = mid;
            else
                right = mid - 1;
        }
        ans = max(ans, R - L + 1);
    }
    pr(ans);
    return 0;
}

 

posted @ 2021-03-31 23:36  PdrEam  阅读(164)  评论(0编辑  收藏  举报