题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=6183
题意
给
你
一
个
二
维
平
面
,
最
开
始
平
面
上
没
有
任
何
点
,
有
4
种
操
作
,
给你一个二维平面,最开始平面上没有任何点,有4种操作,
给你一个二维平面,最开始平面上没有任何点,有4种操作,
第
一
种
操
作
是
0
表
示
清
除
这
个
平
面
上
所
有
的
点
第一种操作是 \ 0 \ 表示清除这个平面上所有的点
第一种操作是 0 表示清除这个平面上所有的点
第
二
种
操
作
是
1
x
y
c
表
示
在
(
x
,
y
)
上
添
加
一
个
颜
色
为
c
的
点
第二种操作是1\ x \ y\ c 表示在(x,y)上添加一个颜色为c的点
第二种操作是1 x y c表示在(x,y)上添加一个颜色为c的点
第
三
种
操
作
是
2
x
y
1
y
2
查
询
(
1
,
y
1
)
,
(
x
,
y
2
)
之
间
有
多
少
种
颜
色
第三种操作是2\ x \ y_1 \ y_2 查询(1,y1),(x,y2)之间有多少种颜色
第三种操作是2 x y1 y2查询(1,y1),(x,y2)之间有多少种颜色
第
四
种
操
作
是
3
表
示
直
接
退
出
程
序
第四种操作是3\ 表示直接退出程序
第四种操作是3 表示直接退出程序
下
标
范
围
1
0
6
,
最
多
有
50
种
颜
色
下标范围10^6,最多有50种颜色
下标范围106,最多有50种颜色
1
,
2
操
作
最
多
1.5
∗
1
0
5
次
1,2操作最多1.5*10^5次
1,2操作最多1.5∗105次
做法
我
们
想
想
只
有
一
种
颜
色
怎
么
办
,
由
于
左
界
限
已
经
固
定
我们想想只有一种颜色怎么办,由于左界限已经固定
我们想想只有一种颜色怎么办,由于左界限已经固定
这
就
意
味
着
我
们
可
以
对
y
建
立
权
值
线
段
树
这就意味着我们可以对y建立权值线段树
这就意味着我们可以对y建立权值线段树
更
新
操
作
只
要
保
留
每
个
y
位
置
最
小
的
x
就
可
以
更新操作只要保留每个y位置最小的x就可以
更新操作只要保留每个y位置最小的x就可以
这
样
查
询
的
时
候
只
要
看
这
个
颜
色
在
(
y
1
,
y
2
)
这
个
区
间
的
最
小
值
是
不
是
小
于
x
这样查询的时候只要看这个颜色在(y1,y2)这个区间的最小值是不是小于x
这样查询的时候只要看这个颜色在(y1,y2)这个区间的最小值是不是小于x
小
于
则
代
表
这
个
颜
色
在
这
个
范
围
内
出
现
过
小于则代表这个颜色在这个范围内出现过
小于则代表这个颜色在这个范围内出现过
但
是
本
题
有
50
种
颜
色
,
这
就
意
味
着
我
们
可
以
建
50
颗
线
段
树
分
别
计
算
但是本题有50种颜色,这就意味着我们可以建50颗线段树分别计算
但是本题有50种颜色,这就意味着我们可以建50颗线段树分别计算
但
是
这
个
数
据
范
围
明
显
会
M
L
E
,
这
时
候
我
们
就
需
要
动
态
开
点
的
线
段
树
但是这个数据范围明显会MLE,这时候我们就需要动态开点的线段树
但是这个数据范围明显会MLE,这时候我们就需要动态开点的线段树
每
次
更
新
一
条
链
上
的
信
息
,
返
回
这
个
颜
色
对
应
的
新
的
根
节
点
下
标
每次更新一条链上的信息,返回这个颜色对应的新的根节点下标
每次更新一条链上的信息,返回这个颜色对应的新的根节点下标
这
样
每
次
更
新
操
作
只
会
产
生
l
o
g
个
新
节
点
,
就
没
有
M
L
E
的
问
题
这样每次更新操作只会产生log个新节点,就没有MLE的问题
这样每次更新操作只会产生log个新节点,就没有MLE的问题
注
意
一
定
要
先
继
承
之
前
的
信
息
,
再
更
新
本
次
更
新
的
信
息
,
保
证
之
前
的
信
息
被
继
承
下
来
。
注意一定要先继承之前的信息,再更新本次更新的信息,保证之前的信息被继承下来。
注意一定要先继承之前的信息,再更新本次更新的信息,保证之前的信息被继承下来。
代码
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1e6+10;
int tot,minn[maxn*4],lson[maxn*4],rson[maxn*4],root[55];
void init()
{
tot=0;
memset(minn,INF,sizeof(minn));
memset(lson,0,sizeof(lson));
memset(rson,0,sizeof(rson));
memset(root,0,sizeof(root));
}
void update(int &now,int l,int r,int pos,int val)
{
if(!now)
{
now=++tot;
minn[now]=val;
}
if(l==r)
{
minn[now]=min(minn[now],val);
return ;
}
int mid=(l+r)>>1;
if(pos<=mid) update(lson[now],l,mid,pos,val);
else update(rson[now],mid+1,r,pos,val);
minn[now]=min(minn[lson[now]],minn[rson[now]]);
return ;
}
int query(int now,int ql,int qr,int l,int r,int maxx)
{
if(!now) return 0;
if(ql<=l&&qr>=r)
{
if(minn[now]<=maxx) return 1;
else return 0;
}
int mid=l+r>>1;
int ans=0;
if(ql<=mid) ans=query(lson[now],ql,qr,l,mid,maxx);
if(ans>0) return 1;
if(qr>mid) ans=query(rson[now],ql,qr,mid+1,r,maxx);
if(ans>0) return 1;
else return 0;
}
int main()
{
int op,x,y,c,y1,y2;
while(scanf("%d",&op)!=EOF)
{
if(op==0)
{
init();
}
else if(op==1)
{
scanf("%d%d%d",&x,&y,&c);
update(root[c],1,1000000,y,x);
}
else if(op==2)
{
scanf("%d%d%d",&x,&y1,&y2);
int ans=0;
for(int i=0;i<=50;i++)
{
ans+=query(root[i],y1,y2,1,1000000,x);
}
printf("%d\n",ans);
}
else
{
break;
}
}
return 0;
}