Color it HDU - 6183

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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值