Time Limit: 2.0 Seconds Memory Limit: 65536K
Total Runs: 292 Accepted Runs: 75
There are N birds in a 2D space, let x and y denote their coordinate in each dimension.
As an excellent shooter, you can shoot down all the birds in the 2D space. But you think that's too cruel.
In order to make the shooting procedure more interesting, you come up with a rule:
At the beginning, you can choose any bird to shoot.
Afterwards, you can only shoot the bird whose coordinate is not smaller than the previous one in each dimension.
For example, if you want to shoot three birds a, b and c then the following relationship must hold:
xa≤xb, ya≤yb, xb≤xc, yb≤yc.
With this rule and coordinates of all the N birds, can you figure out how many birds you can shoot as many as possible?
Input
First line will be a positive integer T indicating the test case number. Following there are T (1≤T≤10) test cases.
Each test case begins with a positive integer N (1≤N≤100000), the number of birds.
Then following N lines with two positive integers x and y (1≤x,y≤100000), which are the coordinates of each bird (you can assume no two birds have the same coordinates).
Output
For each test case output only one integer representing the maximal number of birds you can shoot.
Sample Input
2 3 1 1 2 2 3 3 3 1 1 2 3 3 2
Sample Output
3 2
题意:每次打鸟必须比上次比上次高,问最多打多少鸟
题目分析:线段树水过去,有o(n)的算法,在我的博客中能找到,这道题看代码把
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#define MAX 100007
using namespace std;
int t,n;
struct Bird
{
int x,y;
bool operator < ( const Bird & a ) const
{
if ( x == a.x ) return y < a.y;
return x < a.x;
}
}a[MAX];
struct Tree
{
int l,r,maxn;
}tree[(MAX+1)<<2];
void build ( int u , int l , int r )
{
tree[u].l = l , tree[u].r = r;
tree[u].maxn = 0;
if ( l == r ) return;
int mid = l + r >> 1;
build ( u<<1 , l , mid );
build ( u<<1|1 , mid+1 , r );
}
void push_up ( int u )
{
tree[u].maxn = max ( tree[u<<1].maxn , tree[u<<1|1].maxn );
}
void update ( int u , int x , int v )
{
int l = tree[u].l , r = tree[u].r;
if ( l == r )
{
tree[u].maxn = max ( v , tree[u].maxn );
return;
}
int mid = l + r >>1;
if ( x > mid ) update ( u<<1|1 , x , v );
else update ( u<<1 , x , v );
push_up ( u );
}
int query ( int u , int left , int right )
{
int l = tree[u].l , r = tree[u].r;
if ( left <= l && r <= right )
return tree[u].maxn;
int mid = l + r >> 1;
int maxn = 0;
if ( left <= mid && l <= right ) maxn = max ( maxn , query ( u<<1 , left , right ) );
if ( left <= r && right > mid ) maxn = max ( maxn , query ( u<<1|1 , left , right ) );
return maxn;
}
int main ( )
{
scanf ( "%d" , &t );
while ( t-- )
{
scanf ( "%d" , &n );
for ( int i = 1 ; i <= n ; i++ )
scanf ( "%d%d" , &a[i].x , &a[i].y );
sort ( a+1 , a+n+1 );
build ( 1 , 1 , MAX-2 );
int ans = 0;
for ( int i = 1 ; i <= n ; i++ )
{
int num = query ( 1 , 1 , a[i].y ) + 1;
ans = max ( ans , num );
update ( 1 , a[i].y , num );
}
printf ( "%d\n" , ans );
}
}