HDU 3874 Necklace 树状数组 + 离线处理
2013-10-18 23:44
369 查看
/** * 树状数组 + 离线: * 看人题解的,思路: 把询问区间[l, r]存下后按r从小到大排序 * 用数组hash[i]记录数字i最后一次出现的位置。用变量curR从1开始每次 * 往右扫到每个询问区间的r。关键在于没扫到新的一个数的时候,如何更新 * 维护这个树状数组。把每次询问的答案记录到ans数组。 * 具体: 当前数num[curR]如果出现过,则最后一次出现位置为hash[num[curR]] * 更新update(hash[num[curR]], -num[curR]),每次新的数不管是不是出现过, * 都要update(curR, num[curR]), 因为询问的规则是重复的数只记录一次,那么 * 在前一条语句update(hash[num[curR]], -num[curR])意思是把之前维护的树状数组 * 在hash[num[curR]]的位置减去-num[curR]。 * 为什么要减? * 每次询问的答案是get_sum(r) - get_sum(l - 1) 也就是前r和减去前(l-1)和 * 可是要保证重复的数只计算一次,这样在用curR扫到当前询问的r的时候,扫到重复数的 * 时候就要减去之前的,并在当前出现的位置加上当前的数。 这样就能保住前缀和正确维护了。 */ #include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <string> #include <queue> #include <map> #include <vector> #include <algorithm> #define DEBUG 0 #define INF 0x3fffffff #define OUTSTARS printf("*****************************\n"); #define MAXN 50005 typedef long long LL; using namespace std; LL c[MAXN], ans[200005]; int num[MAXN]; struct Q { int l, r, NO; bool operator < (const Q &a) const { return r < a.r; } } queries[200005]; int n, m; map<int, int> hash; int lowbit(int x) { return x & (-x); } void update(int pos, int val) { for(int i = pos; i <= n; i += lowbit(i)) c[i] += val; } LL query(int pos) { LL ret = 0; for(int i = pos; i > 0; i -= lowbit(i)) ret += c[i]; return ret; } int main() { int t; scanf("%d", &t); while(t --) { scanf("%d", &n); memset(c, 0, sizeof(c)); for(int i = 1; i <= n;i ++) scanf("%d", &num[i]); scanf("%d", &m); for(int i = 1; i <= m; i ++) { scanf("%d%d", &queries[i].l, &queries[i].r); if(queries[i].l > queries[i].r) swap(queries[i].l, queries[i].r); queries[i].NO = i; } sort(queries + 1, queries + 1 + m); hash.clear(); int curR = 1; for(int i = 1; i <= m; i ++) { while(curR <= queries[i].r) { if(hash[num[curR]] != 0) { update(hash[num[curR]], -num[curR]); } hash[num[curR]] = curR; update(curR, num[curR]); curR ++; } ans[queries[i].NO] = query(queries[i].r) - query(queries[i].l - 1); } for(int i = 1; i <= m; i ++) printf("%I64d\n", ans[i]); } return 0; }
相关文章推荐
- HDU 3874 Necklace (树状数组 | 线段树 的离线处理)
- HDU 3874 Necklace(树状数组离线处理)
- HDU 3874 Necklace(树状数组离线处理)
- HDU 3874 树状数组 + 离线处理
- HDU 3333&&HDU-3874 Necklace 离线树状数组
- HDU 3874 Necklace 离线+树状数组
- hdu 3874 Necklace 树状数组 离线操作
- hdu 3874 树状数组 离线处理
- HDU 3874 Necklace(树状数组的离线操作)
- HDU 3874 Necklace(树状数组的离线操作)
- HDU-3874 Necklace 树状数组+离线处理
- hdu-4630-No Pain No Game-(树状数组,离线处理)
- HDU - 3874 Necklace (线段树 + 离线处理)
- HDU 3874 Necklace (树状数组)
- hdu 4630 多校第二场 树状数组,离线处理
- hdu 4417 树状数组 离线处理
- HDU 3874 Necklace(树状数组+离线处理)
- HDU(3874)树状数组+离线
- hdu 3874 Necklace (树状数组)
- hdu 3874 Necklace(树状数组的灵活应用)