Problem Description
After inventing Turing Tree, 3xian always felt boring when solving problems about intervals, because Turing Tree could easily have the solution. As well, wily 3xian made lots of new problems about intervals. So, today, this sick thing happens again...

Now given a sequence of N numbers A1, A2, ..., AN and a number of Queries(i, j) (1≤i≤j≤N). For each Query(i, j), you are to caculate the sum of distinct values in the subsequence Ai, Ai+1, ..., Aj.

 
Input
The first line is an integer T (1 ≤ T ≤ 10), indecating the number of testcases below.
For each case, the input format will be like this:
* Line 1: N (1 ≤ N ≤ 30,000).
* Line 2: N integers A1, A2, ..., AN (0 ≤ Ai ≤ 1,000,000,000).
* Line 3: Q (1 ≤ Q ≤ 100,000), the number of Queries.
* Next Q lines: each line contains 2 integers i, j representing a Query (1 ≤ i ≤ j ≤ N).
 
Output
For each Query, print the sum of distinct values of the specified subsequence in one line.
 
Sample Input
2
3
1 1 4
2
1 2
2 3
5
1 1 2 1 3
3
1 5
2 4
3 5
 
Sample Output
1
5
6
3
6

【题意】给出n个数,然后提出m个问题,求区间内不重复的数之和。

【思路】先按查询的右坐标升序排列(保证我查询的改动不会影响到后面查询的结果)。把每个数放进线段树的时候,先判断再之前他有没有在线段树,如果在,则删除它,并把他的位置更新到当前点。

线段树:

  1. #include<iostream>
  2. #include<stdio.h>
  3. #include<map>
  4. #include<string.h>
  5. #include<algorithm>
  6. using namespace std;
  7. typedef long long int LL;
  8. const int N=+;
  9. const int M=+;
  10. int n,m;
  11. struct node1
  12. {
  13. int l,r;
  14. LL num;
  15.  
  16. }sum[N*];
  17. struct node
  18. {
  19. int ll,rr,index;
  20.  
  21. }q[M];
  22. bool cmp(node x,node y)//按他的右边界排序
  23. {
  24. return x.rr<y.rr;
  25. }
  26. LL a[N];
  27. map<LL,int>mp;//记录是否出现过相同的数,如果有记录位置
  28. LL ans[M];
  29. void build(int k,int l,int r)//建树
  30. {
  31. sum[k].l=l;
  32. sum[k].r=r;
  33. sum[k].num=;
  34. if(l==r) return ;
  35. int mid=l+r>>;
  36. build(k*,l,mid);
  37. build(k*+,mid+,r);
  38. }
  39. void update(int k,int l,int r,int x,LL v)//更新结点的值
  40. {
  41. if(l==r)
  42. {
  43. sum[k].num+=v;
  44. return ;
  45. }
  46. int mid=l+r>>;
  47. if(x<=mid) update(k*,l,mid,x,v);
  48. else update(k*+,mid+,r,x,v);
  49. sum[k].num=sum[k*].num+sum[k*+].num;
  50. }
  51. LL query(int k,int l,int r,int ll,int rr)//查询区间的值
  52. {
  53. if(l>=ll&&r<=rr)
  54. {
  55. return sum[k].num;
  56. }
  57. int mid=l+r>>;
  58. LL res=;
  59. if(ll<=mid) res+=query(k*,l,mid,ll,rr);
  60. if(rr>mid) res+=query(k*+,mid+,r,ll,rr);
  61. return res;
  62. }
  63. int main()
  64. {
  65. int t;
  66. scanf("%d",&t);
  67. while(t--)
  68. {
  69. mp.clear();
  70. scanf("%d",&n);
  71. for(int i=;i<=n;i++)
  72. {
  73. scanf("%I64d",&a[i]);
  74. }
  75. build(,,n);
  76. scanf("%d",&m);
  77. for(int i=;i<m;i++)
  78. {
  79. scanf("%d%d",&q[i].ll,&q[i].rr);
  80. q[i].index=i;
  81. }
  82. sort(q,q+m,cmp);
  83. int k=;
  84. for(int i=;i<m;i++)
  85. {
  86. for(;k<=q[i].rr;k++)
  87. {
  88. if(mp[a[k]]!=) update(,,n,mp[a[k]],-a[k]);//如果曾经出现过,则将以前的结点删去
  89. mp[a[k]]=k;//将位置赋给当前的结点
  90. update(,,n,k,a[k]);//将当前结点更新到树中
  91. }
  92. ans[q[i].index]=query(,,n,q[i].ll,q[i].rr);
  93. }
  94. for(int i=;i<m;i++) printf("%I64d\n",ans[i]);
  95. }
  96. return ;
  97. }

树状数组:

  1. #include<iostream>
  2. #include<stdio.h>
  3. #include<string.h>
  4. #include<map>
  5. #include<algorithm>
  6. using namespace std;
  7. const int N=+;
  8. int n,m,a[N];
  9. long long sum[N*],ans[N*];
  10. map<int,int >mp;
  11. struct node
  12. {
  13. int l,r,id;
  14. bool operator<(const node &a)const{
  15. if(r==a.r) return l<a.l;
  16. return r<a.r;
  17. }
  18. }q[N*];
  19. int lowbit(int x)
  20. {
  21. return x&(-x);
  22. }
  23. void update(int p,int v)
  24. {
  25. while(p<=n)
  26. {
  27. sum[p]+=v;
  28. p+=lowbit(p);
  29. }
  30. }
  31. long long int query(int p)
  32. {
  33. long long int res=;
  34. while(p)
  35. {
  36. res+=sum[p];
  37. p-=lowbit(p);
  38. }
  39. return res;
  40. }
  41. int main()
  42. {
  43. int t;
  44. scanf("%d",&t);
  45. while(t--)
  46. {
  47. mp.clear();
  48. memset(sum,,sizeof(sum));
  49. scanf("%d",&n);
  50. for(int i=;i<=n;i++)
  51. {
  52. scanf("%d",&a[i]);
  53. }
  54. scanf("%d",&m);
  55. for(int i=;i<m;i++)
  56. {
  57. int l,r;
  58. scanf("%d%d",&l,&r);
  59. q[i].l=l;q[i].r=r;q[i].id=i;
  60. }
  61. sort(q,q+m);
  62. int cnt=;
  63. for(int i=;i<=n;i++)
  64. {
  65. if(mp.find(a[i])==mp.end())//在mp中没有找到
  66. {
  67. update(i,a[i]);
  68. mp[a[i]]=i;
  69. }
  70. else
  71. {
  72. update(i,a[i]);
  73. update(mp[a[i]],-a[i]);
  74. mp[a[i]]=i;
  75. }
  76. while(q[cnt].r==i)
  77. {
  78. ans[q[cnt].id]=query(q[cnt].r)-query(q[cnt].l-);
  79. cnt++;
  80. }
  81. }
  82. for(int i=;i<m;i++) printf("%lld\n",ans[i]);
  83. }
  84. return ;
  85. }

Turing Tree_线段树&树状数组的更多相关文章

  1. CodeForces -163E :e-Government (AC自动机+DFS序+树状数组)

    The best programmers of Embezzland compete to develop a part of the project called "e-Governmen ...

  2. HDU 3333 Turing Tree 离线 线段树/树状数组 区间求和单点修改

    题意: 给一个数列,一些询问,问你$[l,r]$之间不同的数字之和 题解: 11年多校的题,现在属于"人尽皆知傻逼题" 核心思想在于: 对于一个询问$[x,R]$ 无论$x$是什么 ...

  3. Hdu-3333 Turning Tree (离线树状数组/线段树)

    Hdu-3333 Turning Tree 题目大意:先给出n个数字.面对q个询问区间,输出这个区间不同数的和. 题解:这道题有多重解法.我另一篇博客写了分块的解法  HDU-3333 Turing ...

  4. [bzoj1901][zoj2112][Dynamic Rankings] (整体二分+树状数组 or 动态开点线段树 or 主席树)

    Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has ...

  5. HDU 1556 线段树或树状数组,插段求点

    1.HDU 1556  Color the ball   区间更新,单点查询 2.题意:n个气球,每次给(a,b)区间的气球涂一次色,问最后每个气球各涂了几次. (1)树状数组 总结:树状数组是一个查 ...

  6. HDU 3966 Aragorn's Story 树链剖分+树状数组 或 树链剖分+线段树

    HDU 3966 Aragorn's Story 先把树剖成链,然后用树状数组维护: 讲真,研究了好久,还是没明白 树状数组这样实现"区间更新+单点查询"的原理... 神奇... ...

  7. 【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings

    谁再管这玩意叫树状数组套主席树我跟谁急 明明就是树状数组的每个结点维护一棵动态开结点的权值线段树而已 好吧,其实只有一个指针,指向该结点的权值线段树的当前结点 每次查询之前,要让指针指向根结点 不同结 ...

  8. HDU 1394 Minimum Inversion Number(最小逆序数/暴力 线段树 树状数组 归并排序)

    题目链接: 传送门 Minimum Inversion Number Time Limit: 1000MS     Memory Limit: 32768 K Description The inve ...

  9. POJ 2299 Ultra-QuickSort 逆序数 树状数组 归并排序 线段树

    题目链接:http://poj.org/problem?id=2299 求逆序数的经典题,求逆序数可用树状数组,归并排序,线段树求解,本文给出树状数组,归并排序,线段树的解法. 归并排序: #incl ...

随机推荐

  1. (3) 深入理解Java Class文件格式(二)

    好文转载:http://blog.csdn.net/zhangjg_blog/article/details/21487287 在上一篇文章 深入理解Java Class文件格式(一) 中, 介绍了c ...

  2. PetaPoco入门(二)

    1. Petapoco基本用法 1.1. 创建示例工程 首先创建一个工程文件,为了便于展示数据这里创建一个类型为:WindowsApplication的工程文件.命名为:PetapocoTest. 程 ...

  3. Java中byte与16进制字符串的互相转换

    * Convert byte[] to hex string.这里我们可以将byte转换成int,然后利用Integer.toHexString(int)来转换成16进制字符串. * @param s ...

  4. NavBarControl

    https://documentation.devexpress.com/#WindowsForms/clsDevExpressXtraNavBarNavBarControltopic Views h ...

  5. ffmpeg从AVFrame取出yuv数据到保存到char*中

    ffmpeg从AVFrame取出yuv数据到保存到char*中   很多人一直不知道怎么利用ffmpeg从AVFrame取出yuv数据到保存到char*中,下面代码将yuv420p和yuv422p的数 ...

  6. 分方式缓存常用的一致性hash是什么原理

    分方式缓存常用的一致性hash是什么原理 一致性hash是用来解决什么问题的?先看一个场景有n个cache服务器,一个对象object映射到哪个cache上呢?可以采用通用方法计算object的has ...

  7. json和xml数据的解析

    一 json数据 1一条json就像一个对象,也想像OC中的数组,且内嵌了很多键值对字典 {"name" : "jack", "age" : ...

  8. js 原生对象排序

    //对象属性排序 function compare(propertyName) { return function (object1, object2) { var value1 = object1[ ...

  9. Linux 下 git连接github的使用

    1.安装git sudo apt-get install git 2.创建github帐号 3.Linux创建SSH密钥: ssh-keygen  //一直默认 4.将公钥加入到Github账户信息A ...

  10. Java完成最简单的WebService创建及使用(REST方式,Jersey框架)

    前言: 一直以来都对WebService感兴趣,但因为难以理解WebService到底是什么,所以了解甚少.周二的时候有个跟我关系比较好的同事想要自己写个WebService的小Demo,希望能够做成 ...