HDU - 6183 - Color it
考虑对每种颜色做一棵线段树,维护每个
y
坐标上的最小
复杂度是
O(50×106log106)
,一种剪枝方法是先读入所有操作然后离散化,这样复杂度可以降到
O(50×3×105log3×105)
,还有一种剪枝方法就是如果已经询问到比输入
x
小的 return
。这道题用其中任何一个剪枝应该都能过。。
还有一种方法是cdq分治。。不过还不会
#include<bits/stdc++.h>
using namespace std;
const int H=1e6,N=150000*30,INF=1e9+7;
int root[57],mn[N],ls[N],rs[N],tot,X;
bool ok;
int newnode()
{
mn[++tot]=INF;
ls[tot]=rs[tot]=0;
return tot;
}
void update(int &rt,int l,int r,int p,int val)
{
if(!rt) rt=newnode();
mn[rt]=min(mn[rt],val);
if(l==r) return ;
int m=(l+r)>>1;
if(p<=m) update(ls[rt],l,m,p,val);
else update(rs[rt],m+1,r,p,val);
}
void query(int rt,int l,int r,int ql,int qr)
{
if(ok) return;
if((ql<=l&&qr>=r)||(ls[rt]==0&&rs[rt]==0))
{
if(mn[rt]<=X) ok=true;
return ;
}
int m=(l+r)>>1;
if(ql<=m&&ls[rt]) query(ls[rt],l,m,ql,qr);
if(qr>m&&rs[rt]) query(rs[rt],m+1,r,ql,qr);
}
int main()
{
int op;
tot=0;
for(int i=0;i<=50;++i) root[i]=newnode();
while(~scanf("%d",&op))
{
if(op==3) break;
if(op==0)
{
tot=0;
for(int i=0;i<=50;++i) root[i]=newnode();
}
if(op==1)
{
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
update(root[c],1,H,y,x);
}
else if(op==2)
{
int x,y1,y2,ans=0;
scanf("%d%d%d",&x,&y1,&y2);
X=x;
for(int i=0;i<=50;++i)
{
ok=false;
query(root[i],1,H,y1,y2);
ans+=ok;
}
printf("%d\n",ans);
}
}
return 0;
}