HDU 4391 Paint the Wall(块状链表 | 分段哈希)
2013-09-27 17:07
351 查看
题目链接:Click here~~
题意:
有 n 个点,每个点有一种颜色(可能相同),两种操作:1、将区间 [a,b] 染成颜色 c ; 2、询问区间 [a,b] 中颜色为 c 的点有多少个。
解题思路:
如果颜色的种类很少(5 个以内),那么就是经典的线段树区间染色的入门题。
但此题颜色太多,虽然可以进行哈希,但是规模还是能达到 10^5,根本不能朴素的用线段树实现。
不过大家很多都用线段树加优化过的。(维护区间颜色种类的最小值和最大值,可在查询时进行优化)
但感觉靠谱的思路还是块状链表,题解叫做分段哈希。
思路是:每个块维护一个 map<color,cnt> 。
然后对于更新操作中跨过的整块,直接将对应的 map 清空,加入新的颜色,长度为 block_len,不用更新对应单点的颜色。
对于两端不够一整块的部分,由于很可能出现多种颜色,所以一定要暴力将单点颜色更新掉。
其实整体思想就是当整块的颜色不唯一时,单点的值才要对应住真实值。这样可以保证更新某个整块时是 O(1) 的。看不懂的话看代码吧。。。。。
开始怕超时不敢用 map 实现,但后来听大家说大胆用 map,于是就写了一个,终于2个小时调出来了,注意修改最后一个块时下标不要超过 n。
题意:
有 n 个点,每个点有一种颜色(可能相同),两种操作:1、将区间 [a,b] 染成颜色 c ; 2、询问区间 [a,b] 中颜色为 c 的点有多少个。
解题思路:
如果颜色的种类很少(5 个以内),那么就是经典的线段树区间染色的入门题。
但此题颜色太多,虽然可以进行哈希,但是规模还是能达到 10^5,根本不能朴素的用线段树实现。
不过大家很多都用线段树加优化过的。(维护区间颜色种类的最小值和最大值,可在查询时进行优化)
但感觉靠谱的思路还是块状链表,题解叫做分段哈希。
思路是:每个块维护一个 map<color,cnt> 。
然后对于更新操作中跨过的整块,直接将对应的 map 清空,加入新的颜色,长度为 block_len,不用更新对应单点的颜色。
对于两端不够一整块的部分,由于很可能出现多种颜色,所以一定要暴力将单点颜色更新掉。
其实整体思想就是当整块的颜色不唯一时,单点的值才要对应住真实值。这样可以保证更新某个整块时是 O(1) 的。看不懂的话看代码吧。。。。。
开始怕超时不敢用 map 实现,但后来听大家说大胆用 map,于是就写了一个,终于2个小时调出来了,注意修改最后一个块时下标不要超过 n。
#include <map> #include <math.h> #include <stdio.h> #include <string.h> #include <assert.h> #include <algorithm> using namespace std; #define size(v) (int)v.size() const int N = 1e5 + 5; int n,color,a ,block_len; map<int,int> blocks_colors[333]; void bf_update(int l,int r) { int block_id = l / block_len; if(size(blocks_colors[block_id]) == 1) { map<int,int>::iterator it = blocks_colors[block_id].begin(); int old_color = it->first; int old_cnt = it->second; if(color == old_color) return ; if(r - l + 1 == old_cnt) { blocks_colors[block_id][color] = r - l + 1; blocks_colors[block_id].erase(it); return ; } for(int i=block_len*block_id;i<n && i<block_len*(block_id+1);i++) { if(i >= l && i <= r) a[i] = color; else a[i] = old_color; } blocks_colors[block_id][color] = r - l + 1; blocks_colors[block_id][old_color] = old_cnt - (r - l + 1); } else { for(int i=l;i<=r;i++) { if(a[i] == color) continue; map<int,int>::iterator it = blocks_colors[block_id].find(a[i]); if(it->second == 1) blocks_colors[block_id].erase(it); else it->second--; blocks_colors[block_id][color]++; a[i] = color; } } } int bf_query(int l,int r) { int block_id = l / block_len; if(blocks_colors[block_id].count(color)) { if(size(blocks_colors[block_id]) == 1) return r - l + 1; else { int ret = 0; for(int i=l;i<=r;i++) if(a[i] == color) ++ret; return ret; } } else return 0; } void update(int l,int r) { int block_id1 = l / block_len; int block_id2 = r / block_len; if(block_id1 == block_id2) { bf_update(l,r); return ; } int rr = block_len * (block_id1 + 1) - 1; int ll = block_len * block_id2; bf_update(l,rr); bf_update(ll,r); for(int id=block_id1+1;id<block_id2;id++) { blocks_colors[id].clear(); blocks_colors[id][color] = block_len; } } int query(int l,int r) { int block_id1 = l / block_len; int block_id2 = r / block_len; if(block_id1 == block_id2) return bf_query(l,r); int rr = block_len * (block_id1 + 1) - 1; int ll = block_len * block_id2; int ret = bf_query(l,rr) + bf_query(ll,r); for(int id=block_id1+1;id<block_id2;id++) if(blocks_colors[id].count(color)) ret += blocks_colors[id][color]; return ret; } void debug(int n,int max_id) { printf("color of a[]: "); for(int i=0;i<n;i++) printf("%d ",a[i]); puts("***"); for(int i=0;i<=max_id;i++) { printf("the %dth block[%d,%d]=>\n",i,i*block_len,(i+1)*block_len-1); for(map<int,int>::iterator it=blocks_colors[i].begin();it!=blocks_colors[i].end();it++) printf("\t\t\t %d -> %d\n",it->first,it->second); puts(""); } } int main() { //freopen("in.ads","r",stdin); int m; while(~scanf("%d%d",&n,&m)) { block_len = (int)sqrt(n * 1.0); //block_len = 400; for(int i=0;i<n;i++) scanf("%d",&a[i]); int block_id_max = n / block_len; for(int i=0;i<=block_id_max;i++) blocks_colors[i].clear(); for(int i=0;i<n;i++) { int block_id = i / block_len; blocks_colors[block_id][ a[i] ]++; } int op,l,r; while(m--) { scanf("%d%d%d%d",&op,&l,&r,&color); if(op == 1) update(l,r); else printf("%d\n",query(l,r)); } } return 0; }
相关文章推荐
- hdu 4391 Paint The Wall(根N分段哈希)
- HDU 4391 Paint The Wall [分块哈希]
- HDU 4391 Paint The Wall
- 【分段哈希】H. Paint the Wall
- 【HDU4391】【块状链表】Paint The Wall
- HDU 4391 Paint The Wall 段树(水
- HDU 4391 Paint The Wall
- HDU 4391 Paint The Wall(分块HASH||线段树)
- 【HDU】4391 Paint The Wall
- hdu 4391 Paint The Wall
- HDU 4391 Paint The Wall 线段树(水
- hdu 4391 Paint The Wall 线段树
- Hdu 4391 Paint The Wall
- hdu Paint the Wall 1543
- hdu1543 Paint the Wall
- hdu 1543 Paint the Wall(线段树)
- 【Unsolved】[HDOJ4391]Paint The Wall(分块,线段树)
- hdu 1543 Paint the Wall
- hdu 1543 Paint the Wall
- hdu 1543 Paint the Wall