VK Cup 2015 - Round 1 -E. Rooks and Rectangles 线段树最值+扫描线

题意: n * m的棋盘, k个位置有"rook"(车),q次询问,问是否询问的方块内是否每一行都有一个车或者每一列都有一个车? 满足一个即可

先考虑第一种情况, 第二种类似,swap一下就可以了。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
inline int GetIdx(int l, int r){
    return l + r | l != r;
}
int seg[maxn << 2];
void update(int l, int r, int x, int d){
    if (l == r){
        seg[GetIdx(l, r)] = d;
        return;
    }
    int mid = (l + r) >> 1;
    if (x <= mid){
        update(l, mid, x, d);
    }else{
        update(mid+1, r, x, d);
    }
    seg[GetIdx(l, r)] = min(seg[GetIdx(l, mid)], seg[GetIdx(mid+1, r)]);
}
int query(int l, int r, int ua, int ub){
    if (ua <= l && ub >= r){
        return seg[GetIdx(l, r)];
    }
    int mid = (l + r) >> 1;
    int res = 1 << 30;
    if (ua <= mid){
        res = min(res, query(l, mid, ua, ub));
    }
    if (ub > mid){
        res = min(res, query(mid+1, r, ua, ub));
    }
    return res;
}
vector <int> line[maxn];
pair <int, int> rook[maxn << 1], rec1[maxn << 1], rec2[maxn << 1];
bool ans[maxn << 1];
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif
    int n, m, k, q;
    while (~scanf ("%d%d%d%d", &n, &m, &k, &q)){
        for (int i = 0; i < k; i++){
            scanf ("%d%d", &rook[i].first, &rook[i].second);
        }
        for (int i = 0; i < q; i++){
            scanf ("%d%d%d%d", &rec1[i].first, &rec1[i].second, &rec2[i].first, &rec2[i].second);
        }
        for (int cas = 1; cas <= 2; cas++){
            memset(seg, 0, sizeof seg);
            for (int i = 1; i <= n; i++){
                line[i].clear();
            }
            for (int i = 0; i < k; i++){
                // 所有rook[i].first上的rook放入line里
                line[rook[i].first].push_back(rook[i].second);
            }
            for (int i = 0; i < q; i++){
                //所有方格右边界线为rec2[i].first的放入line里
                line[rec2[i].first].push_back(~i);
            }
            for (int i = 1; i <= n; i++){
                for (int j = 0; j < line[i].size(); j++){
                    int tmp = line[i][j];
                    if (tmp < 0){
                        tmp = ~tmp;
                        // 查找区间最值判断是否满足
                        if (query(1, m, rec1[tmp].second, rec2[tmp].second) >= rec1[tmp].first){
                            ans[tmp] = true;
                        }
                    }else{
                        update(1, m, tmp, i);
                    }
                }
            }
            swap(n, m);
            for (int i = 0; i <k ;i++){
                swap(rook[i].first, rook[i].second);
            }
            for (int i = 0; i < q; i++){
                swap(rec1[i].first, rec1[i].second);
                swap(rec2[i].first, rec2[i].second);
            }
        }
        for (int i = 0; i < q; i++){
            puts(ans[i] ? "YES" : "NO");
        }
    }
    return 0;
}

 

posted @ 2015-10-22 23:07  PlasticSpirit  阅读(316)  评论(0编辑  收藏  举报