首先这道题的数据范围极大,那么一定是要离散化的,离散化就是读入之后,记录id,分别按照x和y排序,排序之后重新记录成连续的坐标
然后数据量也挺大,而且没有重点,所以直接极角排序,然后将横坐标映射到一棵线段树上,对y排序,然后逐渐将当前y坐标下的点更新到线段树中,在线的更新查询数对,然后另开一个数组记录答案.
对于线段树要维护的东西,其实就是因为k比较小,所以我们直接开10的数组,然后利用归并排序,这样就是可以在线段树上动态的更新每段上当前的有序前k大,所以最后答案可以进行o(1)的查询.
感觉我的算法比较清晰,一步一步来还是可以做的,但作为弱菜的我做了3个小时.......好伤感,还好1A.
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <algorithm>
#define MAX 30007
using namespace std;
int n,m;
struct Building
{
int x,y,h;
bool operator < ( const Building& a ) const
{
return y < a.y;
}
}b[MAX];
struct Query
{
int x,y,k,id;
bool operator < ( const Query& a ) const
{
return y < a.y;
}
}q[MAX];
struct Discret
{
int x , y ,id;
}d[MAX<<1];
bool cmp1 ( Discret d1 , Discret d2 )
{
return d1.x < d2.x;
}
bool cmp2 ( Discret d1 , Discret d2 )
{
return d1.y < d2.y;
}
struct Node
{
int l,r,pre[12];
}tree[MAX<<2];
void push_up ( int u )
{
int id1 = 1 , id2 = 1 , id = 1;
while ( tree[u<<1].pre[id1]!= -1 && tree[u<<1|1].pre[id2] != -1 )
{
if ( id > 10 ) break;
if ( tree[u<<1].pre[id1] < tree[u<<1|1].pre[id2] )
tree[u].pre[id++] = tree[u<<1].pre[id1++];
else tree[u].pre[id++] = tree[u<<1|1].pre[id2++];
}
while ( tree[u<<1].pre[id1] != -1 )
{
if ( id > 10 ) break;
tree[u].pre[id++] = tree[u<<1].pre[id1++];
}
while ( tree[u<<1|1].pre[id2] != -1 )
{
if ( id > 10 ) break;
tree[u].pre[id++] = tree[u<<1|1].pre[id2++];
}
// cout << "root " << u <<" " <<tree[u].l << " " << tree[u].r<< endl;
// for ( int i = 1 ; i <= 10 ; i++ )
// cout << tree[u].pre[i] << " ";
// cout << endl;
}
void build ( int u , int left , int right )
{
memset ( tree[u].pre , -1 , sizeof ( tree[u].pre ) );
tree[u].l = left , tree[u].r = right;
if ( left == right ) return;
int mid = left + right >>1;
build ( u<<1 , left , mid );
build ( u<<1|1 , mid+1 , right );
}
void update ( int u , int h , int x )
{
int l = tree[u].l , r = tree[u].r;
if ( l == r )
{
if ( tree[u].pre[1] == -1 ) tree[u].pre[1] = h;
else
{
int i;
for ( i = 11 ; i >= 2 ; i++ )
{
if ( tree[u].pre[i-1] == -1 ) continue;
if ( tree[u].pre[i] == -1 )
tree[u].pre[i] = h;
}
while ( tree[u].pre[i] < tree[u].pre[i-1] )
{
int temp = tree[u].pre[i];
tree[u].pre[i] = tree[u].pre[i-1];
tree[u].pre[i-1] = temp;
i--;
}
tree[u].pre[11] = -1;
}
return;
}
int mid = l + r >> 1;
if ( x >= l && x <= mid )
update ( u<<1 , h , x );
else
update ( u<<1|1 , h , x );
push_up ( u );
}
struct Array
{
int a[12];
Array ( )
{
memset ( a , -1 , sizeof ( a ) );
}
};
Array query ( int u , int left , int right )
{
int l = tree[u].l , r = tree[u].r;
int mid = l + r >> 1;
Array ret;
if ( left <= l && r <= right )
{
/* cout << "______________________" << endl;
cout << l << " " << r << " " << endl;
for ( int i = 1 ; i <= 10 ; i++ )
cout << tree[u].pre[i] << " ";
cout << endl;
cout << " ++++++++++++++++++++++" << endl;*/
for ( int i = 1 ; i <= 10 ; i++ )
ret.a[i] = tree[u].pre[i];
return ret;
}
Array temp1 , temp2;
if ( left <= mid && right >= l )
temp1 = query ( u<<1 , left , right );
if ( left <= right && right > mid )
temp2 = query ( u<<1|1 , left , right );
int id1 = 1 , id2 = 1 , id = 1;
while ( temp1.a[id1] != -1 && temp2.a[id2] != -1 )
{
if ( id > 10 ) break;
if ( temp1.a[id1] < temp2.a[id2] )
ret.a[id++] = temp1.a[id1++];
else ret.a[id++] = temp2.a[id2++];
}
while ( temp1.a[id1] != -1 )
{
if ( id > 10 ) break;
ret.a[id++] = temp1.a[id1++];
}
while ( temp2.a[id2] != -1 )
{
if ( id > 10 ) break;
ret.a[id++] = temp2.a[id2++];
}
return ret;
}
int ans[MAX];
int main ( )
{
while ( ~scanf ( "%d%d" , &n , &m ) )
{
for ( int i = 1 ; i <= n; i++ )
{
scanf ( "%d%d%d" , &d[i].x , &d[i].y, &b[i].h );
d[i].id = i;
}
for ( int i = 1 ; i <= m ; i++ )
{
scanf ( "%d%d%d" , &d[i+n].x , &d[i+n].y , &q[i].k );
d[i+n].id = i+n;
q[i].id = i;
}
sort ( d+1 , d+n+m+1 , cmp1 );
int cnt1 = 1 , cnt2 = 1;
if ( d[1].id > n ) q[d[1].id-n].x = cnt1;
else b[d[1].id].x = cnt1;
for ( int i = 2 ; i <= n+m ; i++ )
{
if ( d[i].x != d[i-1].x ) cnt1++;
if ( d[i].id > n ) q[d[i].id-n].x = cnt1;
else b[d[i].id].x = cnt1;
}
sort ( d+1 , d+n+m+1 , cmp2 );
if ( d[1].id > n ) q[d[1].id-n].y = cnt2;
else b[d[1].id].y = cnt2;
for ( int i = 2 ; i <= n+m ; i++ )
{
if ( d[i].y != d[i-1].y ) cnt2++;
if ( d[i].id > n ) q[d[i].id-n].y = cnt2;
else b[d[i].id].y = cnt2;
}
sort ( b+1 , b+n+1 );
sort ( q+1 , q+m+1 );
build ( 1 , 1 , cnt1 );
int j = 1;
for ( int i = 1 ; i <= m ; i++ )
{
int y = q[i].y;
while ( b[j].y <= y )
{
update ( 1 , b[j].h , b[j].x );
// cout << "Okay: " << j << " " << b[j].h << " " << b[j].x << endl;
if ( j >= n ) break;
j++;
}
Array record = query ( 1 , 1 , q[i].x );
/* cout << "Id : " << q[i].id << " " << q[i].x << endl;
for ( int t = 1 ; t <= 10 ; t++ )
cout << record.a[t] << " ";
cout << endl;*/
ans[q[i].id] = record.a[q[i].k];
}
for ( int i = 1 ; i <= m ; i++ )
printf ( "%d\n" , ans[i] );
}
}