题目
二维平面,读入若干行,每一行对应一次操作,操作分4种:
0:清掉平面内所有点
1 x y c(1<=x<=1e6,1<=y<=1e6,0<=c<=50):在(x,y)加入一个颜色为c的点,点重合时同时存在
2 x y1 y2(1<=x<=1e6,1<=y1<=y2<=1e6):统计以(1,y1)左下角以(x,y2)右上角这个矩形内点的颜色数
3:退出程序
数据保证只有最后一行是3操作,连续的1或2操作只有最多15W个(即每逢15W就清零一次),0操作最多只有10次
思路来源
https://www.cnblogs.com/lipeiyi520/p/10961683.html
题解1
首先考虑每次查询的左下角都是1,
画出图来,发现是一个以y轴为底边的矩形,
则其中的点的x值越小越容易被包含在询问里,
所以按y轴建线段树,维护x的最小值,
每个颜色开一棵1e6的线段树,这样时间是可行的O(10*1e5*log1e6),但是空间O(50*1e6*4)不大行
所以51个颜色对应的线段树都写成动态开点的,
颜色i对应的树的树根是root[i],有点像主席树那个写法
查询即对每个颜色暴力[y1,y2]内的x的最小值是不是小于当前询问的x即可
代码1
#include<bits/stdc++.h>
using namespace std;
const int N=1e6;
int op,u,v,w,root[55],cnt;
//主席树动态开点思想
struct node{
int l,r,mn;
node():l(0),r(0),mn(N){}
}e[N*4];
void newnode(int &p){
p=++cnt;
e[p].l=e[p].r=0;
e[p].mn=N;
}
void upd(int &p,int l,int r,int x,int v){
if(!p){
newnode(p);
}
if(l==r){
e[p].mn=min(e[p].mn,v);
return;
}
int mid=(l+r)/2;
if(x<=mid)upd(e[p].l,l,mid,x,v);
else upd(e[p].r,mid+1,r,x,v);
e[p].mn=min(e[e[p].l].mn,e[e[p].r].mn);
}
bool ask(int p,int l,int r,int ql,int qr,int v){
if(ql>qr)return 0;
if(!p)return 0;
if(ql<=l&&r<=qr){
return e[p].mn<=v;
}
int mid=(l+r)/2;
if(ql<=mid && ask(e[p].l,l,mid,ql,qr,v))return 1;
if(qr>mid && ask(e[p].r,mid+1,r,ql,qr,v))return 1;
return 0;
}
int main(){
while(~scanf("%d",&op) && op!=3){
if(op==0){
for(int i=0;i<=50;++i){
root[i]=0;
}
cnt=0;
}
else if(op==1){
scanf("%d%d%d",&u,&v,&w);
upd(root[w],1,N,v,u);//按y轴建 维护x的最小值
}
else if(op==2){
scanf("%d%d%d",&u,&v,&w);
int ans=0;
for(int i=0;i<=50;++i){
ans+=ask(root[i],1,N,v,w,u);
}
printf("%d\n",ans);
}
}
return 0;
}
题解2
考虑cdq分治,清零/退出的时候再回答答案,把询问离线,
这样要处理时间序上1的修改对2的回答的影响,
所以是一个类似(时间,x,y)的三维偏序问题,默认时间增序排序
归并的时候考虑[l,mid]对[mid+1,r]的影响,
其实可以忽略[l,mid]内的查询操作,但为了方便排序写法上让修改更靠前
优先处理[l,mid]的修改操作①,同是修改操作的显然x更小的应先遍历②,同是查询操作的无所谓③
①、②、③确定了回溯的时候[l,r]的排序方式,归并的时候就按x增序归并即可
查询的时候,由于x小的都已经插入BIT,
此时,查询[y1,y2]内被插入的点的种类数,51种,这个可以1<<51二进制取或来维护
cdq时间是动态开点线段树的一半你敢信
代码2
代码待补
二维平面上的颜色点统计与操作

该博客讨论了一种二维平面上的颜色点管理问题,涉及四种操作:清除所有点、添加点、统计矩形区域内点的颜色数以及退出程序。文章提供了两种解决方案:一种使用动态开点的线段树,另一种采用CDQ分治策略。这两种方法在时间和空间复杂度上有不同的权衡。
1847

被折叠的 条评论
为什么被折叠?



