http://acm.hdu.edu.cn/showproblem.php?pid=6183
两种操作 对一个点着色 查询矩形内所有颜色
发现查询中的最小的横坐标始终是1 这就好处理多了 因为颜色我打算状压处理 没法前后缀相减
一开始动态主席树直接搞 对每一行建立一棵线段树 因为第i棵线段树维护的是从1到i行的前缀 所以需要套树状数组来优化这个前缀和 至于每棵线段树内开个longlong状压即可
但是空间实在太小了 在RE与MLE之间来回试探 就很绝望。。
然后发现这其实就是一个三位偏序问题啊 查询先后作为第一维 x为第二维 y为第三维 然后CDQ分治就好 具体就是第二维作为合并标准 第三维用线段树维护 还是状压 空间少了十多倍 时间也快了很多
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
struct node0
{
int tp;
int x;
int y1;
int y2;
int c;
int id;
};
struct node1
{
int l;
int r;
ll val;
};
node0 order[600010],tmp[600010];
node1 tree[2000010];
ll pre[100],ans[1500010];
int tmpx[300010],tmpy[600010];
int tot,lenx,leny,cnt,num;
template <class T>
inline void _cin1(T &ret)
{
char c;
ret = 0;
while((c = getchar()) < '0' || c > '9');
while(c >= '0' && c <= '9')
{
ret = ret * 10 + (c - '0');
c = getchar();
}
}
void init()
{
int i;
pre[0]=1;
for(i=1;i<=50;i++) pre[i]=2ll*pre[i-1];
}
void build(int l,int r,int cur)
{
int m;
tree[cur].l=l;
tree[cur].r=r;
tree[cur].val=0;
if(l==r) return;
m=(l+r)/2;
build(l,m,2*cur);
build(m+1,r,2*cur+1);
}
void updateI(int tar,ll val,int cur)
{
tree[cur].val|=val;
if(tree[cur].l==tree[cur].r) return;
if(tar<=tree[2*cur].r) updateI(tar,val,2*cur);
else updateI(tar,val,2*cur+1);
}
void updateII(int tar,ll val,int cur)
{
tree[cur].val=0;
if(tree[cur].l==tree[cur].r) return;
if(tar<=tree[2*cur].r) updateII(tar,val,2*cur);
else updateII(tar,val,2*cur+1);
}
ll query(int pl,int pr,int cur)
{
ll res;
if(pl<=tree[cur].l&&tree[cur].r<=pr) return tree[cur].val;
res=0;
if(pl<=tree[2*cur].r) res|=query(pl,pr,2*cur);
if(pr>=tree[2*cur+1].l) res|=query(pl,pr,2*cur+1);
return res;
}
void cdq(int l,int r)
{
int m,p,q,cnt,i;
if(l==r) return;
m=(l+r)/2;
cdq(l,m);
cdq(m+1,r);
p=l,q=m+1,cnt=l;
while(p<=m&&q<=r)
{
if(order[p].x<=order[q].x)
{
if(order[p].tp==1) updateI(order[p].y1,pre[order[p].c],1);
tmp[cnt++]=order[p++];
}
else
{
if(order[q].tp==2) ans[order[q].id]|=query(order[q].y1,order[q].y2,1);
tmp[cnt++]=order[q++];
}
}
while(q<=r)
{
if(order[q].tp==2) ans[order[q].id]|=query(order[q].y1,order[q].y2,1);
tmp[cnt++]=order[q++];
}
for(i=l;i<p;i++)
{
if(order[i].tp==1) updateII(order[i].y1,0,1);
}
while(p<=m) tmp[cnt++]=order[p++];
for(i=l;i<=r;i++) order[i]=tmp[i];
}
void solve(int len)
{
int i;
//printf("*%d*\n",len);
lenx=0,leny=0;
for(i=1;i<=len;i++)
{
if(order[i].tp==1)
{
tmpx[++lenx]=order[i].x;
tmpy[++leny]=order[i].y1;
}
else
{
tmpx[++lenx]=order[i].x;
tmpy[++leny]=order[i].y1;
tmpy[++leny]=order[i].y2;
}
}
sort(tmpx+1,tmpx+lenx+1);
lenx=unique(tmpx+1,tmpx+lenx+1)-tmpx-1;
sort(tmpy+1,tmpy+leny+1);
leny=unique(tmpy+1,tmpy+leny+1)-tmpy-1;
for(i=1;i<=len;i++)
{
if(order[i].tp==1)
{
order[i].x=lower_bound(tmpx+1,tmpx+lenx+1,order[i].x)-tmpx;
order[i].y1=lower_bound(tmpy+1,tmpy+leny+1,order[i].y1)-tmpy;
}
else
{
order[i].x=lower_bound(tmpx+1,tmpx+lenx+1,order[i].x)-tmpx;
order[i].y1=lower_bound(tmpy+1,tmpy+leny+1,order[i].y1)-tmpy;
order[i].y2=lower_bound(tmpy+1,tmpy+leny+1,order[i].y2)-tmpy;
}
}
cdq(1,len);
//printf("***\n");
}
int main()
{
int i,p;
init();
build(1,300000,1);
tot=1,lenx=0,leny=0,cnt=0,p=0;
for(i=1;;i++)
{
//scanf("%d",&order[tot].tp);
_cin1(order[tot].tp);
if(order[tot].tp==1)
{
//scanf("%d%d%d",&order[tot].x,&order[tot].y1,&order[tot].c);
_cin1(order[tot].x);
_cin1(order[tot].y1);
_cin1(order[tot].c);
}
else if(order[tot].tp==2)
{
//scanf("%d%d%d",&order[tot].x,&order[tot].y1,&order[tot].y2);
_cin1(order[tot].x);
_cin1(order[tot].y1);
_cin1(order[tot].y2);
if(order[tot].y1>order[tot].y2) swap(order[tot].y1,order[tot].y2);
order[tot].id=++cnt;
}
else
{
if(p+1<=i-1) solve(i-p-1);
if(order[tot].tp==3) break;
tot=0;
p=i;
}
tot++;
}
for(i=1;i<=cnt;i++)
{
p=0;
while(ans[i]>0)
{
p+=ans[i]%2;
ans[i]/=2;
}
printf("%d\n",p);
}
return 0;
}