hdu 5107 K-short Problem 線段樹掃描線

分析:題意是給一個二維平面,平面有一些點給出座標x,y和高度h,然後m個詢問,每次詢問 小於等於x,y這個點的點集中h第k小的點。我們觀察到由於題目中k很小隻有10,所以我們可以用線段樹維護y軸,把點轉換成掃描線,從左到右掃過,遇到建築則更新線段樹,遇到query則查詢。每個節點,我們只需要維護區間的前10小的點的高度即可。然後更新點的時候直接按照大小在區間插入即可,然後查詢的時候用一個大頂堆維護K個最小值即可,當然,由於點的座標很大,需要對點離散化。值得一提的是,沒必要要把查詢的點的y座標和平面上點的y座標一起離散化成線段樹的區間維護,直接代入查詢即可。這樣做的話時間從750MS提到了650MS,因爲對空間的需求和遞歸的深度都會低很多。詳見代碼:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
struct Point{
    int x, y, h, type, id;//0爲建築 1爲查詢點
}p[60006];
int ans[30003];
struct Tnode{
    int a[11];
    int num;
}node[30006<<2];
int yy[30006];
priority_queue<int> q;

bool operator<(const Point &a, const Point &b){
    return a.x < b.x || a.x == b.x && a.y < b.y || a.x == b.x && a.y == b.y && a.type < b.type;
}

void inline _insert(int *first, int *last, int key){
    while(last > first && *(last-1) > key) {*last = *(last-1);last--;}
    *last = key;
}
void update(int rt, int l, int r, int y, int key){
    _insert(node[rt].a, node[rt].a+node[rt].num, key);
    if(node[rt].num < 10) node[rt].num++;
    if(l != r){
        int mid = l + r >> 1;
        if(y <= yy[mid]) update(rt<<1, l, mid, y, key);
        else update(rt<<1|1, mid+1, r, y, key);
    }
}


inline void add_queue(int rt, int k){
    for(int i = 0; i < node[rt].num; i++){
        q.push(node[rt].a[i]);
        if(q.size() > k) q.pop();
    }
}
void query(int rt, int l, int r, int y, int k){
    if(y < yy[l]) return;
    if(y >= yy[r]){
        add_queue(rt, k);
        return;
    }
    int mid = l + r >> 1;
    if(y <= yy[mid]) query(rt<<1, l, mid, y, k);
    else{
        query(rt<<1, l, mid, y, k);
        query(rt<<1|1, mid+1, r, y, k);
    }
}
int main(){
    int n, m;
    while(scanf("%d%d", &n, &m) == 2){
        memset(node, 0, sizeof(node));
        for(int i = 0; i < n; i++){
            scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].h);
            p[i].type = 0;
            yy[i] = p[i].y;
        }
        for(int i = n; i < m + n; i++){
            scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].h);
            p[i].type = 1;
            p[i].id = i - n;
        }
        sort(p, p + n + m);
        sort(yy, yy + n);
        int mm = unique(yy, yy + n) - yy;
        for(int i = 0; i < m + n; i++){
            if(p[i].type == 0){
                update(1, 0, mm-1, p[i].y, p[i].h);
            }else{
                while(!q.empty()) q.pop();
                query(1, 0, mm-1, p[i].y, p[i].h);
                if(q.size() == p[i].h) ans[p[i].id] = q.top();
                else ans[p[i].id] = -1;
            }
        }
        for(int i = 0; i < m; i++){
            printf("%d\n", ans[i]);
        }
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章