Codeforces 524 E Rooks and Rectangles —— 線段樹+sorting,思維

This way

題意:

現在有一張n*m的棋盤,上面放着k個車,車的攻擊範圍是它所處的這一行或這一列。
q個詢問,每次問你如果只選擇一個矩形的範圍,每個格子是否都處在被攻擊的狀態中。

題解:

補一下以前沒做出來的題目,現在看看發現其實還是蠻簡單的。
首先如果每個格子處在被攻擊的狀態之下,那麼要麼每行或者每列有一個車。
那麼我們就需要一個數據結構能夠查詢矩形中是否每行或者每列都有車。
很明顯直接查是很難的,至少我一下子想不出來。但是我如果從下到上枚舉每行,然後查看一個區間內,這條線上面的最近的車的最大值,那就很容易了。
我用set保存每行/每列的所有的車的列號/行號。然後從下到上枚舉每行/列然後查詢,更新。。。
看着代碼很多,但是其實很多都是重複的,或者是模板

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
set<int>sx[N],sy[N];
int x[N],y[N];
bool ans[N];
struct Query{
    int l,r,h,id;
};
vector<Query>q_x[N],q_y[N];
struct node{
    int mx[N*4];
    void update(int l,int r,int root,int p,int v){
        if(l==r){
            mx[root]=v;
            return ;
        }
        int mid=l+r>>1;
        if(mid>=p)
            update(l,mid,root<<1,p,v);
        else
            update(mid+1,r,root<<1|1,p,v);
        mx[root]=max(mx[root<<1],mx[root<<1|1]);
    }
    int query(int l,int r,int root,int ql,int qr){
        if(l>=ql&&r<=qr)
            return mx[root];
        int ans=0,mid=l+r>>1;
        if(mid>=ql)
            ans=query(l,mid,root<<1,ql,qr);
        if(mid<qr)
            ans=max(ans,query(mid+1,r,root<<1|1,ql,qr));
        return ans;
    }
}tx,ty;

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    int k,q,x,y;
    scanf("%d%d",&k,&q);
    for(int i=1;i<=k;i++)
        scanf("%d%d",&x,&y),sx[x].insert(y),sy[y].insert(x);
    for(int i=1;i<=q;i++){
        int x1,y1,x2,y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        q_x[y1].push_back({x1,x2,y2,i});
        q_y[x1].push_back({y1,y2,x2,i});
    }
    for(int i=1;i<=n;i++){
        if(sx[i].size())
            tx.update(1,n,1,i,*sx[i].begin());
        else
            tx.update(1,n,1,i,1e9);
    }

    for(int i=1;i<=m;i++){
        if(sy[i-1].size()){
            for(auto p:sy[i-1]){
                if(sx[p].size()){
                    set<int>::iterator it=sx[p].lower_bound(i);
                    if(it!=sx[p].end())
                        tx.update(1,n,1,p,*it);
                    else
                        tx.update(1,n,1,p,1e9);
                }
                else
                    tx.update(1,n,1,p,1e9);
            }
        }
        for(auto u:q_x[i])
            ans[u.id]=tx.query(1,n,1,u.l,u.r)<=u.h;
    }
    for(int i=1;i<=m;i++){
        if(sy[i].size())
            ty.update(1,m,1,i,*sy[i].begin());
        else
            ty.update(1,m,1,i,1e9);
    }
    for(int i=1;i<=n;i++){
        if(sx[i-1].size()){
            for(auto p:sx[i-1]){
                if(sy[p].size()){
                    set<int>::iterator it=sy[p].lower_bound(i);
                    if(it!=sy[p].end())
                        ty.update(1,m,1,p,*it);
                    else
                        ty.update(1,m,1,p,1e9);
                }
                else
                    ty.update(1,m,1,p,1e9);
            }
        }
        for(auto u:q_y[i])
            ans[u.id]=max(ans[u.id],ty.query(1,m,1,u.l,u.r)<=u.h);
    }
    for(int i=1;i<=q;i++)
        printf("%s\n",ans[i]?"YES":"NO");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章