【二维偏序】
【二维偏序】
https://zhuanlan.zhihu.com/p/112504092
解题方法
树状数组+离散化
题目整理
小红的线下查询
https://ac.nowcoder.com/acm/contest/116945/F
题目大意
思路
(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;
}
}