HDU 6183 Color it cdq分治 + 线段树 + 状态压缩

Posted Meek

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 6183 Color it cdq分治 + 线段树 + 状态压缩相关的知识,希望对你有一定的参考价值。

Color it

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)


Problem Description
Do you like painting? Little D doesn‘t like painting, especially messy color paintings. Now Little B is painting. To prevent him from drawing messy painting, Little D asks you to write a program to maintain following operations. The specific format of these operations is as follows.

0 : clear all the points.

1 x y c : add a point which color is c at point (x,y).

2 x y1 y2 : count how many different colors in the square (1,y1) and (x,y2). That is to say, if there is a point (a,b) colored c, that 1ax and y1by2, then the color c should be counted.

3 : exit.
 
Input
The input contains many lines. 

Each line contains a operation. It may be ‘0‘, ‘1 x y c‘ ( 1x,y106,0c50 ), ‘2 x y1 y2‘ (1x,y1,y2106 ) or ‘3‘. 

x,y,c,y1,y2 are all integers.

Assume the last operation is 3 and it appears only once.

There are at most 150000 continuous operations of operation 1 and operation 2. 

There are at most 10 operation 0. 

 
Output
For each operation 2, output an integer means the answer .
 
Sample Input
0
1 1000000 1000000 50 
1 1000000 999999 0
1 1000000 999999 0
1 1000000 1000000 49
2 1000000 1000000 1000000
2 1000000 1 1000000 0
1 1 1 1
2 1 1 2
1 1 2 2
2 1 1 2
1 2 2 2
2 1 1 2
1 2 1 3
2 2 1 2
2 10 1 2
2 10 2 2
0 1 1 1
1 2 1 1
1 1 1 2
1 2 1 1
2 1 2 2
1 2 1 1
2 1 2 1
1 2 2 1
2 2 10
1 2 2 10
2 2
3
 
Sample Output
2 3 1 2 2 3 3 1 1 1 1 1 1 1
 
题解:
 
  对于加入的点,我把第一维, x 进行排序, cdq分治优化时间这一维,其余部分用线段树
  因为只有50中颜色,我将每一位颜色进行二进制压缩,当作一个数存在线段树里
  利用线段树查询一个区间有多少不同的颜色(位运算)
  
#include <bits/stdc++.h>

inline int read(){int x=0,f=1;char ch=getchar();while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}return x*f;}
using namespace std;
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
const int N = 1e6 + 10;

namespace IO {
    const int MX = 4e7; //1e7占用内存11000kb
    char buf[MX]; int c, sz;
    void begin() {
        c = 0;
        sz = fread(buf, 1, MX, stdin);
    }
    inline bool read(int &t) {
        while(c < sz && buf[c] != - && (buf[c] < 0 || buf[c] > 9)) c++;
        if(c >= sz) return false;
        bool flag = 0; if(buf[c] == -) flag = 1, c++;
        for(t = 0; c < sz && 0 <= buf[c] && buf[c] <= 9; c++) t = t * 10 + buf[c] - 0;
        if(flag) t = -t;
        return true;
    }
}

struct ss{
    int op,x,y,z,id;
    long long ans;
    ss(int op = 0,int x = 0,int y = 0,int z = 0,int id = 0,long long ans = 0) : op(op), x(x), y(y), z(z), id(id), ans(ans) {}
}Q[N],t[N];

bool cmp(ss s1,ss s2) { if(s1.x == s2.x) return s1.op < s2.op;else return s1.x < s2.x; }

int n,mx,san[N];
void init() {n = 0;}
long long v[N * 20];

void update(int i,int ll,int rr,int x,long long c,int ff) {
    if(ll == rr && x == ll) {if(!ff)v[i] |= 1LL<<c;else v[i] = c;return ;}
    if(x <= mid) update(ls,ll,mid,x,c,ff);
    else update(rs,mid+1,rr,x,c,ff);
    v[i] = v[ls] | v[rs];
}
long long ask(int i,int ll,int rr,int x,int y) {
    if(x > y) return 0;
    if(ll == x && rr == y) return v[i];
    if(y <= mid) return ask(ls,ll,mid,x,y);
    else if(x > mid) return ask(rs,mid+1,rr,x,y);
    else return (ask(ls,ll,mid,x,mid) | ask(rs,mid+1,rr,mid+1,y));
}
void cdq(int ll,int rr) {
    if(ll == rr) return ;
    for(int i = ll; i <= rr; ++i) {
        if(Q[i].id <= mid && Q[i].op == 1)
            update(1,1,mx,Q[i].y,Q[i].z,0);
        else if(Q[i].id > mid && Q[i].op == 2)
            Q[i].ans |= ask(1,1,mx,Q[i].y,Q[i].z);
    }
    for(int i = ll; i <= rr; ++i) {
        if(Q[i].id <= mid && Q[i].op == 1)
            update(1,1,mx,Q[i].y,0,1);
    }
    int L1 = ll, R1 = mid+1;
    for(int i = ll; i <= rr; ++i) {
        if(Q[i].id <= mid) t[L1++] = Q[i];
        else t[R1++] = Q[i];
    }
    for(int i = ll; i <= rr; ++i) Q[i] = t[i];
    cdq(ll,mid);cdq(mid+1,rr);
}
void solve() {
    if(n == 0) return ;
    int cny = 0;
    for(int i = 1; i <= n; ++i) {
        if(Q[i].op == 1) san[++cny] = Q[i].y;
        else {
            san[++cny] = Q[i].y;
            san[++cny] = Q[i].z;
        }
    }
    sort(san+1,san+cny+1);
    int SA = unique(san+1,san+cny+1) - san - 1;
    for(int i = 1; i <= n; ++i) {
        if(Q[i].op == 1) Q[i].y = lower_bound(san+1,san+SA+1,Q[i].y) - san;
        else {
            Q[i].y = lower_bound(san+1,san+SA+1,Q[i].y) - san;
            Q[i].z = lower_bound(san+1,san+SA+1,Q[i].z) - san;
        }
    }
    mx = SA;
    sort(Q+1,Q+n+1,cmp);
    cdq(1,n);
    for(int i = 1; i <= n; ++i) {
        if(Q[i].op == 2) {
            int sum = 0;
            for(int j = 0; j <= 50; ++j)
                if((Q[i].ans >> j) & 1) sum++;
            printf("%d\n",sum);
        }
    }
}
int op,x,z,y;
int main() {
    IO::begin();
    while(1) {
        IO::read(op);
        if(op == 3 || op == 0) {
            solve();
            init();
            if(op == 3) return 0;
            continue;
        }
        IO::read(x);
        IO::read(y);
        IO::read(z);
        Q[++n] = ss(op,x,y,z,n,0);
    }
    return 0;
}

 

 

以上是关于HDU 6183 Color it cdq分治 + 线段树 + 状态压缩的主要内容,如果未能解决你的问题,请参考以下文章

HDU 6183 Color it(动态开点线段树)

HDU6183 Color it 动态开点线段树

HDU 6183 Color it

[hdu6183][Color it]

HDU6183 Color it (线段树动态开点)

HDU - 6183 Color it(动态开点线段树/树状数组套动态开点线段树)