链接:https://ac.nowcoder.com/acm/contest/27302/K
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
Phenix作为食堂的金牌厨师,每天的工作是为同学们准备饭菜,Phenix做出的每一种菜都有一个辣度值,范围是[1,n][1,n]。作为厨师,Phenix提前了解了m位同学的辣度接受范围,第i位同学的辣度接受范围被描述为[l_i,r_i][l
i
,r
i
],表示该同学可以接受辣度值位于这个区间的菜。由于众口难调,每天Phenix会选出部分同学,做出能让这部分同学都接受的辣度的菜。Phenix作为金牌厨师对每天工作的满意程度定义为选出的同学的人数kk和能让这部分同学都接受的菜的种类数xx(这里理解为一种辣度对应一种菜)两者中的最小值,即min(k,x)min(k,x)n,mn,m(1<=n,m<=300000)(1<=n,m<=300000)。
现在你需要想办法让Phenix的满意程度最大。
输入描述:
第一行两个整数n,mn,m,表示菜的辣度最大值和同学的人数(1<=n,m<=300000)(1<=n,m<=300000)。
接下来mm行,每行两个整数l_i,r_il
i
,r
i
依次表示第ii个同学的辣度接受范围(1<=l_i,r_i<=n)(1<=l
i
,r
i
<=n)
输出描述:
一行,表示满意度的最大值。
示例1
输入
复制
5 5
3 5
1 2
2 5
2 5
4 5
输出
复制
3
说明
最优策略为:选择第1,3,4位同学,他们的辣度接受范围分别是[3,5],[2,5],[2,5],所以能让他们都接受的菜的辣度是3,4,5,此时k=3,x=3,满意度=min(k,x)=3
思路 :
- 二分不会写,呜呜呜
#include<cstdio>
#include<iostream>
#include<queue>
const int N = 3e5 + 10;
using namespace std;
struct ll{int r,last;}d[N];
int n,m,ans,num,head[N];
int read(){
int k=0,f=0;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')f=1;
for(;c<='9'&&c>='0';c=getchar())k=(k<<3)+(k<<1)+c-'0';return f?-k:k;
}
bool check(int x){
int cnt = 0;priority_queue<int>q;
for(int i = 1;i + x - 1 <= n;i ++){
for(int t = head[i];t;t = d[t].last)
if(d[t].r >= i + x - 1)cnt++,q.push(-d[t].r);
while(!q.empty()&&-q.top() < i + x - 1)cnt--,q.pop();
if(cnt >= x)return true;
}return false;
}
void Dce(int l,int r){
while(l <= r){
int mid = l + r >> 1;
if(check(mid))ans = mid,l = mid + 1;
else r = mid - 1;
}printf("%d\n",ans);
}
void add(int a,int b){d[++num]=(ll){b,head[a]};head[a]=num;}
int main(){
n = read();m = read();
for(int i = 1;i <= m;i ++){
int a = read(),b = read();
add(a,b);
}
Dce(0,min(n,m));
return 0;
}