HDU - 6183

题目链接:HDU - 6183


本来是需要二维线段树+动态开点的,或者CDQ分治。

但是我们可以注意到查询的时候,左端点的x坐标一直是1,查询的时候也不在乎数量只在乎是否存在。所以我们可以开51颗线段树,分别存每一种颜色,然后按照y坐标插入线段树,查询是否有值小于当前查询的x即可。

当然51颗线段树空间不够,需要动态开点。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6+10,inf=0x3f3f3f3f;
int rt[55],lc[N*4],rc[N*4],mi[N*4],cnt,flag;
void change(int &p,int l,int r,int x,int y){
	if(!p)	p=++cnt;
	if(l==r){mi[p]=min(mi[p],y);	return ;}
	int mid=l+r>>1;
	if(x<=mid)	change(lc[p],l,mid,x,y);
	else	change(rc[p],mid+1,r,x,y);
	mi[p]=min(mi[lc[p]],mi[rc[p]]);
}
void ask(int p,int l,int r,int ql,int qr,int k){
	if(!p||l>r||flag)	return ;
	if(l==ql&&r==qr){if(mi[p]<=k)	flag=1;	return ;}
	int mid=l+r>>1;
	if(qr<=mid)	ask(lc[p],l,mid,ql,qr,k);
	else if(ql>mid)	ask(rc[p],mid+1,r,ql,qr,k);
	else	ask(lc[p],l,mid,ql,mid,k),ask(rc[p],mid+1,r,mid+1,qr,k);
}
inline int calc(int x,int y1,int y2){
	int res=0;
	for(int i=0;i<=50;i++){
		flag=0;	ask(rt[i],1,1e6,y1,y2,x);	res+=flag;
	}
	return res;
}
inline void init(){
	for(int i=0;i<=50;i++)	rt[i]=0;
	for(int i=0;i<=cnt;i++)	lc[i]=rc[i]=0;	cnt=0;
	memset(mi,0x3f,sizeof mi);
}
signed main(){
	while(true){
		static int op,x,y,c,y1,y2;	scanf("%d",&op);
		if(op==0)	init();
		else if(op==1)	scanf("%d %d %d",&x,&y,&c),change(rt[c],1,1e6,y,x);
		else if(op==2)	scanf("%d %d %d",&x,&y1,&y2),printf("%d\n",calc(x,y1,y2));
		else	break;
	}
	return 0;
}
发布了434 篇原创文章 · 获赞 234 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/103971066
hdu