花兒朵朵
時間限制: 1000 ms | 記憶體限制: 65535 KB 難度: 5
- 描述
- 春天到了,花兒朵朵盛開,hrdv是一座大花園的主人,在他的花園裡種着許多種鮮花,每當這個時候,就會有一大群遊客來他的花園欣賞漂亮的花朵,遊客們總是會詢問,某個時間有多少種花兒同時在盛開着?hrdv雖然知道每種花兒的開花時間段,但是他不能很快的答出遊客的問題,你能編寫一個程式幫助他嗎?
- 輸入
- 第一行有個整數t,表示有t組測試資料,每組測試資料第一行為兩個整數n,m(0<n<100000,0<m<100000);随後有n行,每一行有兩個整數x,y(0<x<y<1000000000),表示這一種花的盛開時間是從x到y;随後有m行,每行有一個整數,代表遊客詢問的時間。 輸出
- 對于每次遊客的詢問,輸出一個整數在單獨的一行,表示這個時間盛開的花有多少種。 樣例輸入
-
2 1 1 5 10 4 2 3 1 4 4 8 1 4 6
樣例輸出 -
0 1 2 1
和“士兵殺敵二”相像, 但是資料範圍太大了,不能直接開數組,用離散化,或者哈希 資料有點水,我直接取餘就水過了
#include <algorithm>
#include <iostream>
#include <cstring>//樹狀數組模闆————插入區間求單點
#include <cstdlib>
#include <string>
#include <vector>
#include <cstdio>
#include <cmath>
#include <map>
#define FLAG 0
#define M 999983//一個很大的素數,因為我數組取的是100萬,是以取了100萬以下的最大素數
using namespace std;//這裡可能存在問題,就是沒有去重,如果取餘之後有重複,這樣就不行了
//我想是這一題的資料出的太水了,是以蒙混過關了
int c[1000005];//全局變量數組c 用lowbit函數建立成樹狀數組
int lowbit(int x)//重要建樹、查找、連接配接函數
{
return x&(-x);
}
void add(int x,int d)//區間修改,如果給定阿健a——b上各加d ,
{ //需要調用兩次:add(a-1,-d);add(b,d);
while(x>0)
{
c[x]+=d;x-=lowbit(x);
}
}
int get(int x) //擷取單點的值(查詢)
{
int sum=0;
while(x<1000000)//1000000是數組的最大長度,就是取餘後資料的最大範圍
{
sum+=c[x];x=x+lowbit(x);
}
return sum;
}
int main()
{
#if(FLAG)
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
int n;
int T,m,i,j,x,y;
scanf("%d",&T);
while(T--)
{
memset(c,0,sizeof(c));
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
{
scanf("%d%d",&x,&y);
x=x%M;
y=y%M;//每次都對x,y進行處理之後進行運算
add(x-1,-1);
add(y,1);
}
for(i=0;i<m;i++)
{
scanf("%d",&x);
x=x%M;//詢問的時候做同樣的運算
printf("%d\n",get(x));
}
}
return 0;
}
如果資料卡一點估肯定不過,還是離散化+去重的保險
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lowbit(a) a&-a
#define MaxN 300005
int m[MaxN], real[MaxN], N;
typedef struct
{
int val, pos;
}S;
S mm[MaxN];
bool cmp(S a, S b)
{
if(a.val==b.val) return a.pos>b.pos;
return a.val<b.val;
}
void Add(int i, int num)
{
while(i<=N)
{
m[i]+=num;
i+=lowbit(i);
}
}
int Sum(int i)
{
int res=0;
while(i>0)
{
res+=m[i];
i-=lowbit(i);
}
return res;
}
int main()
{
int T, temp, k, n;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&k);
N=2*n+k;
memset(m,0,sizeof(m));
for(int i=1;i<=N;i++)
{
scanf("%d",&temp);
mm[i].pos=i;
mm[i].val=temp;
}
sort(mm+1,mm+N+1,cmp);
int x=0;
for(int i=1;i<=N;i++) //離散化+去重
{
if( mm[i].val != mm[i-1].val)
real[mm[i].pos]=++x;
else
real[mm[i].pos]=x;
}
for(int i=1;i<=2*n;i+=2) //插線
{
Add(real[i],1);
Add(real[i+1]+1,-1);
}
for(int i=2*n+1;i<=N;i++) //問點
printf("%d\n",Sum(real[i]));
}
return 0;
}