【二维偏序】

【二维偏序】

https://zhuanlan.zhihu.com/p/112504092

解题方法

树状数组+离散化

题目整理

小红的线下查询

https://ac.nowcoder.com/acm/contest/116945/F

题目大意

image

思路

(1)把45°坐标转为直角坐标\(X=x-y\)\(Y=x+y\)
(2)此时查找变成:\(x>-k1\)\(y<k2\) -> 二维偏序
(3)利用离散化+树状数组统计:
将所有数全部塞进v 排序后用map对应id进行离散化
将y塞入树状数组
遍历query,若发现\(<-k1\)直接删点即可,统计\(>k2\)的y值

代码

int n,q;
struct Query{
    int k1,k2;
    int id;
};
void solve(){
    cin>>n>>q;
    vector<PII> a(n+1);
    vector<Query> query(q+1);
    //离散化
    vector<int> v;
    map<int,int> mp;
    for(int i=1,x,y;i<=n;i++){
        cin>>x>>y;
        //坐标转化
        int X=x-y,Y=x+y;
        a[i]={X,Y};
        v.push_back(X);
        v.push_back(Y);
    }
    for(int i=1;i<=q;i++){
        cin>>query[i].k1>>query[i].k2;
        query[i].id=i;
        query[i].k1*=-1;
        v.push_back(query[i].k1);
        v.push_back(query[i].k2);
    }
    //离散化:只关心先后顺序
    sort(v.begin(),v.end());
    int idx=1;
    for(int i=0;i<v.size();i++){
        if(i>0 && v[i]>v[i-1]){//去重
            idx++;
        }
        mp[v[i]]=idx;
    }
    for(int i=1;i<=n;i++){
        auto &[x,y]=a[i];
        x=mp[x];
        y=mp[y];
    }
    for(int i=1;i<=q;i++){
        query[i].k1=mp[query[i].k1];
        query[i].k2=mp[query[i].k2];
    }
    FenwickTree ft((n+q)*2+1);//注意开的空间
    //树状数组存纵坐标
    for(int i=1;i<=n;i++){
        auto &[x,y]=a[i];
        ft.update(y,1);
    }
    sort(a.begin()+1,a.end());
    //离线查询
    sort(query.begin()+1,query.end(),[&](Query x,Query y)->bool{
        return x.k1<y.k1;
    });
    vector<int> ans(q+1,0);
    int i=1;
    for(int j=1;j<=q;j++){
        while(i<=n && a[i].fi<=query[j].k1){
            ft.update(a[i].sc,-1);
            i++;
        }
        ans[query[j].id]=ft.query(query[j].k2-1);
    }
    for(int i=1;i<=q;i++){
        cout<<ans[i]<<endl;
    }
}
posted @ 2025-09-18 13:22  White_ink  阅读(3)  评论(0)    收藏  举报