HDU 3874 Necklace(树状数组+离线处理)
2014-03-19 17:52
381 查看
HDU 3874 Necklace(树状数组+离线处理)
http://acm.hdu.edu.cn/showproblem.php?pid=3874
题意:
有一个由n个整数组成的数列,要求你回答以下询问[L,R]:返回a[L]到a[R]的和。但是其中相同值的元素只能计算一次。比如数列1 1 1 2 3 4 ,如果我们求[1,3]的和,就返回1。如果我们求[2,4]的和,就返回3。
分析:
预处理:首先我们需要一个树状数组A
,我们从左到右读入所有的a[i],如果当前a[i]=x值是第一次出现,就执行add(i,x),否则不执行。当我们扫描完了n个值后,我们保证sum(R)就是区间[1,R]的答案(想想是不是)。
接下来我们对所有查询的区间进行排序,使得[L,R]区间中L小的区间排在前面。我们首先用sum(R)给出所有区间[1,R]的查询。
接着我们要计算所有区间[2,R]的查询,但是做这步前,我们还需要消除a[1]对后面序列的影响,使得我们这个序列就好像是本来就是从a[1]开始的,从来没有存在过a[1]。要完成这个要求,我们只需要执行add(1,-a[1])并且我们需要找到a[1]值第二次出现的位置y执行add(y,a[1])。OK做完上面这步我们就保证了当前的sum(R)就是区间[2,R]的答案(有关区间[3,R],[4,R]等的查询我们目前不管,以后再说)。
所以每当我们查询完了区间[i-1,R]的答案后,我们需要做的操作是:
找到a[i-1]的值出现的下一个位置y(如果不存在为-1时,就默认为n+1位置),执行add(i-1,-a[i-1]) 和 add(y,a[i-1])即可。
我们用next[i]=j来表示与a[i]值相同的下一个值出现在j位置。用hash[h]=i表示值为h的a[i]第一次出现的位置是i。
答案可能超过int 需要用long long
AC代码:1640ms一次AC
http://acm.hdu.edu.cn/showproblem.php?pid=3874
题意:
有一个由n个整数组成的数列,要求你回答以下询问[L,R]:返回a[L]到a[R]的和。但是其中相同值的元素只能计算一次。比如数列1 1 1 2 3 4 ,如果我们求[1,3]的和,就返回1。如果我们求[2,4]的和,就返回3。
分析:
预处理:首先我们需要一个树状数组A
,我们从左到右读入所有的a[i],如果当前a[i]=x值是第一次出现,就执行add(i,x),否则不执行。当我们扫描完了n个值后,我们保证sum(R)就是区间[1,R]的答案(想想是不是)。
接下来我们对所有查询的区间进行排序,使得[L,R]区间中L小的区间排在前面。我们首先用sum(R)给出所有区间[1,R]的查询。
接着我们要计算所有区间[2,R]的查询,但是做这步前,我们还需要消除a[1]对后面序列的影响,使得我们这个序列就好像是本来就是从a[1]开始的,从来没有存在过a[1]。要完成这个要求,我们只需要执行add(1,-a[1])并且我们需要找到a[1]值第二次出现的位置y执行add(y,a[1])。OK做完上面这步我们就保证了当前的sum(R)就是区间[2,R]的答案(有关区间[3,R],[4,R]等的查询我们目前不管,以后再说)。
所以每当我们查询完了区间[i-1,R]的答案后,我们需要做的操作是:
找到a[i-1]的值出现的下一个位置y(如果不存在为-1时,就默认为n+1位置),执行add(i-1,-a[i-1]) 和 add(y,a[i-1])即可。
我们用next[i]=j来表示与a[i]值相同的下一个值出现在j位置。用hash[h]=i表示值为h的a[i]第一次出现的位置是i。
答案可能超过int 需要用long long
AC代码:1640ms一次AC
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int MAXN=50000+1000; const int MAXV=1000000+100; const int MAXM=200000+1000; struct HASHMAP { int head[MAXV];//head[x]=i表示第一个出现的x值下标是i int next[MAXN]; int size; void init() { memset(head,-1,sizeof(head)); } void insert(int i,int v)//将a[i]=v插入到HASHMAP中 { next[i]=-1; if(head[v]==-1) head[v]=i; else { int j=head[v]; while(next[j]!=-1) j=next[j]; next[j]=i; } } int find(int i)//找到a[i]值下一次出现的位置 { return next[i]; } }hm; long long c[MAXN]; int a[MAXN];//初始读入的值 struct node { int l,r; int index; bool operator <(const node&b)const { return l<b.l; } }nodes[MAXM];//查询命令 long long ans[MAXM];//最终答案 int lowbit(int x) { return x&(-x); } long long sum(int x) { long long res=0; while(x) { res +=c[x]; x-=lowbit(x); } return res; } void add(int x,int v) { while(x<MAXN) { c[x]+=v; x+=lowbit(x); } } int main() { int T; scanf("%d",&T); while(T--) { int n,m; scanf("%d",&n); hm.init(); memset(c,0,sizeof(c)); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); if(hm.head[a[i]]==-1)//目前不存在a[i]值 add(i,a[i]); hm.insert(i,a[i]); } scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d%d",&nodes[i].l,&nodes[i].r); nodes[i].index=i; } sort(nodes+1,nodes+m+1); int j=1;//表示当前处理第j个排序后的区间 for(int i=1;i<=n;i++)//从区间[i,R]一一处理 { while(nodes[j].l==i) { ans[nodes[j].index]=sum(nodes[j].r); j++; } if(j>m) break; add(i,-a[i]); int next_ai=hm.find(i); if(next_ai!=-1) add(next_ai,a[i]); } 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 Necklace (树状数组+离线操作)
- HDU 3874 Necklace(树状数组离线处理)
- HDU 3874 Necklace (树状数组 | 线段树 的离线处理)
- hdu 3874 树状数组+离线处理
- HDU - 3874 Necklace(树状数组+离线操作)
- HDU - 3874 Necklace (线段树 + 离线处理)
- hdu 3874 Necklace(离线+树状数组)
- hdu 3874 树状数组+离线处理
- hdu 3874 Necklace(离线操作+树状数组或线段树)
- HDU 3874 离线处理,树状数组
- HDU 3874 Necklace (树状数组+离线操作)
- hdu 3333 Turing Tree (树状数组+离线处理+离散化)
- HDU 3874 Necklace 离线+树状数组
- HDU 5869 Different GCD Subarray Query (离线处理 树状数组)
- [hdu 4417]树状数组+离散化+离线处理
- HDU 3874 Necklace(树状数组)
- HDU 4630 离线处理 + 树状数组