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 1≤a≤x and y1≤b≤y2, then the color c should be counted.
3 : exit.
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 1≤a≤x and y1≤b≤y2, 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' ( 1≤x,y≤106,0≤c≤50 ), '2 x y1 y2' (1≤x,y1,y2≤106 ) 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.
Each line contains a operation. It may be '0', '1 x y c' ( 1≤x,y≤106,0≤c≤50 ), '2 x y1 y2' (1≤x,y1,y2≤106 ) 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; }