HDU 4343 多查询求区间内的最大不相交区间个数-思维&贪心-卡时间&二分&剪枝

题意:给你一些区间,现在有m个查询,求出每个查询的区间内的最大的不相交区间个数

分析:

几天前那道说谎问题时用dp的摞箱子模型求的最大的不相交区间个数,但是这题不能用这个方法,因为这题是动态的查询,不可能每个查询dp一次,超时。

这题用贪心策略。求区间[l~r]里的最大不相交区间,贪心策略就应该先选该区间内右端点最小的,这样给以后待选的区间留下更大的空间,所以我们的做法就是先按照区间的右端点排序,然后每次查询依次挑出查询区间里右端点最小的,并且把查询区间的左端点更新为刚才挑出的区间的右端点(这个处理的作用是保证选出不相交的区间),如果现在访问的区间的右端点已经大于查询区间的右端点,就break跳出循环。挑出第一个右端点最小的区间用二分,注意二分法的应用。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m;
struct node{
	int l,r;
}a[100005];
bool cmp(node a,node b)
{
	return a.r<b.r;
}
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF){
		for(int i=0;i<n;i++) scanf("%d%d",&a[i].l,&a[i].r);
	    sort(a,a+n,cmp);
		int p,q;
		while(m--){
			scanf("%d%d",&p,&q);
			int l=0,r=n-1;
			int pos=-1;
			while(l<=r){
				int mid=(l+r)>>1;
				if(a[mid].r<=p){
					pos=mid;
					l=mid+1;
				}
				else r=mid-1;
			}
		    int tmp=p,ans=0;
		  //  for(int i=0;i<n;i++) cout<<a[i].l<<" "<<a[i].r<<endl;cout<<endl;
			for(int i=pos+1;i<n;i++){
				if(a[i].r<=q){
					if(a[i].l>=tmp){
				//	cout<<a[pos].l<<" "<<a[pos].r<<endl;
						ans++;
						tmp=a[i].r;
				    }
				}
			    else break;
			}
			printf("%d\n",ans);
		}
	}
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-27 04:29:50

HDU 4343 多查询求区间内的最大不相交区间个数-思维&贪心-卡时间&二分&剪枝的相关文章

!HDU 4334 集合各出一数和为0是否存在-思维、卡时间-(指针的妙用)

题意:有5个集合,集合的大小是n,每一个集合出一个数,问能不能找到五个数的和为0.数据范围:T<=50:n<=200 分析: 暴力枚举是n^5*T,超时,那么就要用一些技巧了. 这里有一个指针的妙用:如何在O(n)的复杂度找A,B,使得A+B==C(A,B分别属于一个数列a,b).做法是先把a,b分别按升序排序,然后一个指针i指向a的首,指针j指向b的尾,判定指针指向的数的和是否==C,若等于则结束查找,若小于,则i++,若大于则 j- -,如果有一个指针已经走到了头还没找到A+B==C,则说

Triangle - POJ 2954(求三角形内的格子点的个数)

Pick公式:平面上以格子点为顶点的简单多边形的面积=边上的点数/2+内部的点数+1. 代码如下: ---------------------------------------------------------------------------------------------------------------------------- #include<iostream> #include<string.h> #include<stdio.h> #inclu

给出一个区间[a, b],计算区间内“神奇数”的个数。 神奇数的定义:存在不同位置的两个数位,组成一个两位数(且不含前导0),且这个两位数为质数。 比如:153,可以使用数字3和数字1组成13,13是质数,满足神奇数。同样153可以找到31和53也为质数,只要找到一个质数即满足神奇数。

给出一个区间[a, b],计算区间内"神奇数"的个数.神奇数的定义:存在不同位置的两个数位,组成一个两位数(且不含前导0),且这个两位数为质数.比如:153,可以使用数字3和数字1组成13,13是质数,满足神奇数.同样153可以找到31和53也为质数,只要找到一个质数即满足神奇数. 输入描述: 输入为两个整数a和b,代表[a, b]区间 (1 ≤ a ≤ b ≤ 10000). 输出描述: 输出为一个整数,表示区间内满足条件的整数个数 输入例子: 11 20 输出例子: 6 1 #in

HDU 4417 Super Mario(主席树求区间内的区间查询+离散化)

Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5101    Accepted Submission(s): 2339 Problem Description Mario is world-famous plumber. His “burly” figure and amazing jumping abilit

hdu 5289 Assignment(给一个数组,求有多少个区间,满足区间内的最大值和最小值之差小于k)

1.区间是一段的,不是断开的哟 2.代码是看着标程写的 3.枚举左端点,二分右端点流程: #include<cstdio> #include<cstring> #include<cmath> #define LL long long #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) using namespace std; const int N=200007; int

HDU 3264 区间内的最大最小之差

题目链接:http://poj.org/problem?id=3264 题目大意:在给定一堆牛的数量以及其高度的时候,每次给定一段区间,求这个区间内最高的牛和最矮的牛的高度之差为多少. 这道题目用线段树能快速的求解,因为此处不涉及更新,所以无需写update函数 不同于之前只定义一个tree数组,这回我们需要定义一个Max和一个Min数组分别子弟想存放较大和较小值 通过query找到区间内的最大值q,和最小值p,那么q-p便是我们所求的 1 #include <iostream> 2 #inc

hdu 5381 The sum of gcd(线段树等差数列区间修改+单点查询)

题意: 给出一个数组a,叫你每次询问如下等式的值. f(l,r)=∑ri=l∑rj=igcd(ai,ai+1....aj) 解析: 思考了很久终于理解了学长的思路 给你一个序列,这个序列的子序列gcd的个数不会超过logN个(N为每个数字,最大能取到的范围) 因为求gcd是递减的,每次至少除以2,所以gcd的个数只会有logN个. 然后让我们来看看题目要求的是什么. 所有子区间的gcd的和. 比如[1, 5]这个区间可以分解成如下子区间. [1, 1] [1, 2] [1, 3] [1, 4]

POJ 2761-Feed the dogs(划分树)求区间内第k小的数

Feed the dogs Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 17679   Accepted: 5561 Description Wind loves pretty dogs very much, and she has n pet dogs. So Jiajia has to feed the dogs every day for Wind. Jiajia loves Wind, but not the

POJ 3368 线段树,给定区间求连续不降序列的在该区间内出现最多的数

Frequent values Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 13771   Accepted: 5045 Description You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In addition to that, you are given several queries cons