【HDU - 6183】Color it(CDQ分治 或 动态开点线段树)
題干:
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.?
00?: clear all the points.?
11?xx?yy?cc?: add a point which color is?cc?at point?(x,y)(x,y).?
22?xx?y1y1?y2y2?: count how many different colors in the square?(1,y1)(1,y1)?and?(x,y2)(x,y2). That is to say, if there is a point?(a,b)(a,b)?colored?cc, that?1≤a≤x1≤a≤x?and?y1≤b≤y2y1≤b≤y2, then the color?cc?should be counted.?
33?: 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≤501≤x,y≤106,0≤c≤50?), '2 x y1 y2' (1≤x,y1,y2≤1061≤x,y1,y2≤106?) or '3'.?
x,y,c,y1,y2x,y,c,y1,y2?are all integers.?
Assume the last operation is 3 and it appears only once.?
There are at most?150000150000?continuous operations of operation 1 and operation 2.?
There are at most?1010?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 3Sample Output
2 3 1 2 2 3 3 1 1 1 1 1 1 1題目大意:
解題報告:
直接51顆線段樹,按照y軸建樹,然后維護x的最小值。但是直接建樹會mle,所以考慮動態開點。注意不要手滑寫錯emmm。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define F first #define S second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 1e6 + 5; const int INF = 0x3f3f3f3f; struct TREE {int l,r;int minn; } tree[MAX<<2]; int root[555],tot,flag;void pushup(int rt) {int L = tree[rt].l,R = tree[rt].r;tree[rt].minn = min(tree[L].minn,tree[R].minn); } void update(int &rt,int l,int r,int tar,int x) {if(rt == 0) {rt = ++tot;tree[rt].l = tree[rt].r = 0;tree[rt].minn = x;}if(l == r) {tree[rt].minn = min(tree[rt].minn,x);return;}int m = (l+r)>>1;if(tar <= m) update(tree[rt].l,l,m,tar,x);else update(tree[rt].r,m+1,r,tar,x);pushup(rt); } void query(int rt,int l,int r,int pl,int pr,int x) {if(flag || !rt) return ;if(pl <= l && pr >= r) {if(tree[rt].minn <= x) flag = 1;return ;}int m = (l+r)>>1;if(pl <= m) query(tree[rt].l,l,m,pl,pr,x);if(pr > m) query(tree[rt].r,m+1,r,pl,pr,x); } int main() {int op;tree[0].l = tree[0].r = 0;tree[0].minn = INF;while(scanf("%d",&op)) {if(op == 3) break;if(op == 0) {for(int i = 0; i<=50; i++) root[i] =0;tot=0;}if(op == 1) {int x,y,c;scanf("%d%d%d",&x,&y,&c);update(root[c],1,1000000,y,x);}if(op == 2) {int x,y1,y2,ans = 0;scanf("%d%d%d",&x,&y1,&y2);for(int i = 0; i<=50; i++) {flag = 0;query(root[i],1,1000000,y1,y2,x);ans += flag;}printf("%d\n",ans);} }return 0 ; }總結:
還有一個坑啊,
?? ?tree[0].l = tree[0].r = 0;
?? ?tree[0].minn = INF;
這兩步必須有,因為這里是單點更新,所以update里面的if和else只進去一個,另一邊沒有開點。假設進入了l并且開點了l,那么tree[rt].r=0,所以你pushup的時候直接從右孩子取值直接就變成tree[0].minn了,,所以直接就成0了,所以為了避免這一狀態發生,我們要把0這個節點設置成非法節點,也就是不影響結果就可以,所以我們把tree[0].minn=INF就可以了。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的【HDU - 6183】Color it(CDQ分治 或 动态开点线段树)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 信用卡申请额度一般是多少 抓住这几点申请
- 下一篇: 六大行集体清理一类高息存款,高息存款难觅