【woj3302】doges乱搞解法

【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 零;//你懂的
} 

总结,在一些序列问题不知到如何求解时,可以想一想其他办法,如离散化、差分等等

文章原创,转载请附上原文链接

完结散花

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值