「JOISC 2016 Day 1」俄罗斯套娃(二维偏序)

「JOISC 2016 Day 1」俄罗斯套娃
思路清奇的呀,先在坐标轴上画图(R为横坐标,H为纵坐标),然后发现每个询问之间没有影响,考虑离线处理,因为询问的要求是选择>=R的,所以把横坐标从大到小排序,二维偏序?,那么在H对应的纵坐标上画一条线,就发现是在这以下的娃娃都满足,然后就树状数组维护不可以套起来的,可以画图理解,就是一个娃娃右上方的,答案是所有不能连接的形成的链的最大值,注意一下更新方式,因为最外面的娃娃也算没有套的,所以就是最大值(真一开始没想通)

#include<bits/stdc++.h>
using namespace std;
struct node{
	int x,y,id;/*直径,高度*/
}a[400010];
int cmp(node x,node y){
	if(x.x!=y.x)return x.x>y.x;
	if(x.y!=y.y)return x.y<y.y;
	return x.id<y.id;
}
int tree[400010],l[800010];
int find(int x,int le,int ri){
	int ans=0;
	while(le<=ri){
		int mid=le+ri>>1;
		if(l[mid]<=x)ans=mid,le=mid+1;
		else ri=mid-1;
	}
	return ans;
}
int ans[200010],nn;
void add(int x,int val){
	for(;x<=nn;x+=x&-x)tree[x]=max(tree[x],val);
}
int qu(int x){
	int ans=0;
	for(;x;x-=x&-x)ans=max(ans,tree[x]);
	return ans;
}
int main(){
	int n,q;
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y),a[i].id=0,l[i*2-1]=a[i].x,l[i*2]=a[i].y;
	for(int i=1;i<=q;i++)scanf("%d%d",&a[i+n].x,&a[i+n].y),a[i+n].id=i,l[(i+n)*2-1]=a[i].x,l[(i+n)*2]=a[i].y;
	sort(l+1,l+(q+n)*2+1);
	for(int i=1;i<=(n+q)*2;i++)if(l[i]!=l[i-1])l[++nn]=l[i];
	sort(a+1,a+1+n+q,cmp);//R从大到小 
	for(int i=1;i<=q+n;i++){
		int r=find(a[i].x,1,nn),h=find(a[i].y,1,nn);
		if(!a[i].id)add(h,qu(h)+1/*注意不是加一*/);
		else ans[a[i].id]=qu(h);
	}
	for(int i=1;i<=q;i++)printf("%d\n",ans[i]);
	return 0;
}
posted @ 2022-08-28 13:32  半口学气!  阅读(81)  评论(0编辑  收藏  举报