您的位置:首页 > 大数据 > 人工智能

hdu 4391 Paint The Wall(根N分段哈希)

2012-08-24 14:43 453 查看
将整个区间分为sqrt(n)段小区间,每个段长度为sqrt(n),并维护每一段的统计量,这样可以在sqrt(n)时间内完成一次区间查询或更新。平衡查询和更新之间矛盾是数据结构设计时的重要考虑因素,而这种做法是经典的平衡做法,早就了解,但以前没有遇到过只能用“分段”解决的题目,因此总觉着这是迫不得已的“赖招”,也从来没有写过,昨天第一次写,小细节没注意,结果悲剧的写成每次查询O(n)了。总结一下错误:

1.对于整个区间的更新,不需要实际处理每个元素的值,只需要用一个变量标记一下即可,当整段元素更新量不一致时再更新每个元素,这样才能够保证查询时sqrt(n)的复杂度,否则就O(n)了。。。

2.如果使用map代替哈希表,如果元素不在map中不要直接查询,因为查询不存在的元素会自动插入,空间复杂度会变为n*n。

3.对于最后一段,长度可能与前边的段不同,因此需要特殊处理最后一段的长度。

鉴于java中HashMap效率很客观,自己懒得写哈希表,使用map会增加复杂度,虽然oj支持不好而且不支持下标caoz,最终还是选择了用java搞分段哈希

其它题目:

Spoj3261 Race Against Time修改某个值,查询谋取区间内小于等于k的元素个数

解法:分段+排序/Treap

spoj 861 SWAPS动态维护逆序对

解法:分段/Treap+树状数组(/article/7931941.html

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.HashMap;

public class Hash {
int maxn = 100010, maxm = 335;
class Zone {
HashMap<Integer, Integer> mp = new HashMap<Integer, Integer>();
int color[] = new int[maxm], len, all;
void init(int ln) {
mp.clear();
all = -1;
len = ln;
}
int get(int c) {
if (mp.containsKey(c))
return mp.get(c);
else
return 0;
}
void set(int c) {
all = c;
}
void update(int left, int right, int c) {
if (all == c)
return;
if (all != -1) {
for (int i = 1; i < left; i++)
color[i] = all;
for (int i = right + 1; i <= len; i++)
color[i] = all;
}
for (int i = left; i <= right; i++)
color[i] = c;
all = -1;
mp.clear();
for (int i = 1; i <= len; i++)
mp.put(color[i], get(color[i])+1);
}

int query(int left, int right, int c) {
if (all == -1) {
int sum = 0;
for (int i = left; i <= right; i++)
if (color[i] == c)
sum++;
return sum;
} else {
if (all == c)
return right - left + 1;
else
return 0;
}
}
}
Zone zz[] = new Zone[maxm];
int belong[] = new int[maxn], id[] = new int[maxn];
int a[] = new int[maxn], M;
void build(int n) {
for (int i = 1; i * i <= n; i++)
M = i;
int cnt = 0, len = M;
for (int i = 1; i <= n; i++) {
if (len == M) {
zz[++cnt].init(M);
len = 0;
}
belong[i] = cnt;
id[i] = ++len;
zz[cnt].color[len] = a[i];
zz[cnt].mp.put(a[i], zz[cnt].get(a[i]) + 1);
}
zz[cnt].len = len;
}

void update(int left, int right, int c) {
int l = belong[left], r = belong[right];
if (l == r) {
zz[r].update(id[left], id[right], c);
} else {
zz[l].update(id[left], zz[l].len, c);
for (int i = l + 1; i < r; i++)
zz[i].set(c);
zz[r].update(1, id[right], c);
}
}

int query(int left, int right, int c) {
int sum = 0;
int l = belong[left], r = belong[right];
if (l == r) {
sum += zz[l].query(id[left], id[right], c);
} else {
sum += zz[l].query(id[left], zz[l].len, c);
for (int i = l + 1; i < r; i++) {
if (zz[i].all == c)
sum += zz[i].len;
if(zz[i].all==-1)
sum += zz[i].get(c);
}
sum += zz[r].query(1, id[right], c);
}
return sum;
}
void run() throws IOException {
for (int i = 1; i < maxm; i++)
zz[i] = new Zone();
while (in.nextToken() != in.TT_EOF) {
int n = (int) in.nval;
int m = nextInt();
for (int i = 1; i <= n; i++)
a[i] = nextInt();
build(n);
int t, a, b, c;
while (m-- > 0) {
t = nextInt();
a = nextInt() + 1;
b = nextInt() + 1;
c = nextInt();
if (t == 1)
update(a, b, c);
else
System.out.println(query(a, b, c));
}
}
}
StreamTokenizer in = new StreamTokenizer(new BufferedReader(
new InputStreamReader(System.in)));

int nextInt() throws IOException {
in.nextToken();
return (int) in.nval;
}
public static void main(String[] args) throws IOException {
new Hash().run();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: