• 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
    ",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;
    }
     
  • 相关阅读:
    14-6-27&28自学内容小结
    暑假要自学Java了
    找最大值算法(面试题)
    冒泡排序(面试题)
    循环
    运算符和表达式 、 分支结构 使用三目运算符的嵌套,比较a、b、c三个整数的大小并输出结果
    运算符和表达式 、 分支结构 输入年份和月份,输出该月的天数(使用switch-case)
    运算符和表达式 、 分支结构 3 个数值进行升序排列
    运算符和表达式 、 分支结构 例题 闰年判断
    变量 、 JAVA基本类型 3.3.5. 关于“短路逻辑”的问题
  • 原文地址:https://www.cnblogs.com/zxhl/p/7462417.html
Copyright © 2020-2023  润新知