【woj3302】doges[二分答案]
题意:
描述
在一个遥远的地方,住着 n 只 Doge,它们分别被编号为 1 到 n 之间的正整数。
有一天,一个叫 Jrisme 的人来到这里,进行了一些「虐狗」行为。具体的,Jrisme 每次会虐编号连续的一些 Doge。现给出每次虐狗的区间,求最幸运(被虐次数最多)Doge 被虐了多少次。
输入
第一行两个正整数 n 和 m ,分别表示 Doge 的数量和 Jrisme 的虐狗次数。
从第二行开始,之后的 m 行,第 i 行为两个正整数 li 、ri ,表示 Jrisme 虐了编号在区间 [li,ri] 内的 Doge。
输出
一行一个整数,最幸运的 Doge 的被虐次数。
样例输入
10 3
1 4
4 7
4 9
样例输出
3
提示
对于 30% 的数据,n,m≤1000
对于另外 20% 的数据,n≤10^6 ;
对于另外 20% 的数据,n≤5×10^6
对于另外 20% 的数据,m≤5000
对于 100% 的数据,1≤n≤10^9 ,1≤m≤200000 ,1≤li≤ri≤n
虽然题目的标签写的是二分答案,但是我发现有一种更无脑的解决方式,见下:
先考虑前70分:
n比较小,那么就是进行区间加值,最后跑一边每个点的值的问题,很明显可以用差分解决
代码:
for(int i=1;i<=m;i++)
c[a[i].l]++,c[a[i].r+1]--;
int ans=0,pre=0;
for(int i=1;i<=(m<<1);i++){
pre+=c[i];
if(pre>ans)ans=pre;
}
printf("%d",ans);
至于100分:n很大
我们发现,将所有l和r画在数轴上,相邻两点之间的线段的被虐次数是相同的,也就是说:影响答案的与l和r的值无关,只与所有l和r的关系有关
所以离散化后再差分就可以了
代码中的离散化是手写的,简单来说就是先把所有值排个序,计算离散后的值,最后填回原来的位置,注意相同的值离散后也要相同,所以用一个cnt记录
代码:
#include<bits/stdc++.h>
using namespace std;
#define M 300005
struct node{//离散化后
int l,r;
}a[M];
int n,m;
struct ls{//用于离散
int yuan,wei;
}b[M<<1];
bool cmp(ls x, ls y){
return x.yuan<y.yuan;
}
void lsh(){
sort(b+1,b+2*m+1,cmp);
int cnt=0;
for(int i=1;i<=2*m;i++){
if(b[i].yuan!=b[i-1].yuan)cnt++;
int w=b[i].wei;
if(w%2)a[w/2+1].l=cnt;
else a[w/2].r=cnt;
}
}
int c[M<<1];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m*2;i++){
scanf("%d",&b[i].yuan);
b[i].wei=i;
}
lsh();
for(int i=1;i<=m;i++)
c[a[i].l]++,c[a[i].r+1]--;
int ans=0,pre=0;
for(int i=1;i<=m*2;i++){//离散后至多m*2个点
pre+=c[i];
if(pre>ans)ans=pre;
}
printf("%d",ans);
return 零;//你懂的
}
总结,在一些序列问题不知到如何求解时,可以想一想其他办法,如离散化、差分等等
文章原创,转载请附上原文链接
完结散花