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个问题,求区间内不重复的数之和。

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

线段树:

#include<iostream>
#include<stdio.h>
#include<map>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long int LL;
const int N=+;
const int M=+;
int n,m;
struct node1
{
int l,r;
LL num; }sum[N*];
struct node
{
int ll,rr,index; }q[M];
bool cmp(node x,node y)//按他的右边界排序
{
return x.rr<y.rr;
}
LL a[N];
map<LL,int>mp;//记录是否出现过相同的数,如果有记录位置
LL ans[M];
void build(int k,int l,int r)//建树
{
sum[k].l=l;
sum[k].r=r;
sum[k].num=;
if(l==r) return ;
int mid=l+r>>;
build(k*,l,mid);
build(k*+,mid+,r);
}
void update(int k,int l,int r,int x,LL v)//更新结点的值
{
if(l==r)
{
sum[k].num+=v;
return ;
}
int mid=l+r>>;
if(x<=mid) update(k*,l,mid,x,v);
else update(k*+,mid+,r,x,v);
sum[k].num=sum[k*].num+sum[k*+].num;
}
LL query(int k,int l,int r,int ll,int rr)//查询区间的值
{
if(l>=ll&&r<=rr)
{
return sum[k].num;
}
int mid=l+r>>;
LL res=;
if(ll<=mid) res+=query(k*,l,mid,ll,rr);
if(rr>mid) res+=query(k*+,mid+,r,ll,rr);
return res;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
mp.clear();
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%I64d",&a[i]);
}
build(,,n);
scanf("%d",&m);
for(int i=;i<m;i++)
{
scanf("%d%d",&q[i].ll,&q[i].rr);
q[i].index=i;
}
sort(q,q+m,cmp);
int k=;
for(int i=;i<m;i++)
{
for(;k<=q[i].rr;k++)
{
if(mp[a[k]]!=) update(,,n,mp[a[k]],-a[k]);//如果曾经出现过,则将以前的结点删去
mp[a[k]]=k;//将位置赋给当前的结点
update(,,n,k,a[k]);//将当前结点更新到树中
}
ans[q[i].index]=query(,,n,q[i].ll,q[i].rr);
}
for(int i=;i<m;i++) printf("%I64d\n",ans[i]);
}
return ;
}

树状数组:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<map>
#include<algorithm>
using namespace std;
const int N=+;
int n,m,a[N];
long long sum[N*],ans[N*];
map<int,int >mp;
struct node
{
int l,r,id;
bool operator<(const node &a)const{
if(r==a.r) return l<a.l;
return r<a.r;
}
}q[N*];
int lowbit(int x)
{
return x&(-x);
}
void update(int p,int v)
{
while(p<=n)
{
sum[p]+=v;
p+=lowbit(p);
}
}
long long int query(int p)
{
long long int res=;
while(p)
{
res+=sum[p];
p-=lowbit(p);
}
return res;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
mp.clear();
memset(sum,,sizeof(sum));
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
}
scanf("%d",&m);
for(int i=;i<m;i++)
{
int l,r;
scanf("%d%d",&l,&r);
q[i].l=l;q[i].r=r;q[i].id=i;
}
sort(q,q+m);
int cnt=;
for(int i=;i<=n;i++)
{
if(mp.find(a[i])==mp.end())//在mp中没有找到
{
update(i,a[i]);
mp[a[i]]=i;
}
else
{
update(i,a[i]);
update(mp[a[i]],-a[i]);
mp[a[i]]=i;
}
while(q[cnt].r==i)
{
ans[q[cnt].id]=query(q[cnt].r)-query(q[cnt].l-);
cnt++;
}
}
for(int i=;i<m;i++) printf("%lld\n",ans[i]);
}
return ;
}

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. easyui editor combobox multiple

    $.extend($.fn.datagrid.defaults.editors,{ combobox: { init: function(container, options){ var combo ...

  2. Bootstrap_标签

    一.标签 在一些Web页面中常常会添加一个标签用来告诉用户一些额外的信息,比如说在导航上添加了一个新导航项,可能就会加一个“new”标签,来告诉用户. 那么在Bootstrap框架中特意将这样的效果提 ...

  3. Postman Postman测试接口之POST提交本地文件数据

    举例: 文件同步接口 接口地址:http://183.xxx.xxx.xxx:23333/ditui/fileupload HTTP请求方式:POST 针对上述这种POST本地文件的接口,接口数据咋提 ...

  4. 【OOAD】设计模式概述

    模式的诞生与定义 模式起源于建筑业而非软件业模式(Pattern)之父——美国加利佛尼亚大学环境结构中心研究所所长Christopher Alexander博士<A Pattern Langua ...

  5. Android studio环境搭建

    首先要下载jdk,下载好以后配置环境变量,这里略过,不会的可以百度搜索,这里附上jdk下载地址:http://pan.baidu.com/s/1Xrmqy 下载Android studio 软件,下载 ...

  6. Pycharm使用问题# Interpreter设置

    Pycharm可以迅速更换interpreter版本. 在菜单栏选择File-Settings打开Settings设置对话框,选择展开Interpreter选项: 使用列表右侧的+和—即可增加和删除I ...

  7. webstrom使用方法

    一.设置file-settings- -color&fonts设置,字体 主体 -file and code templates模板ctrl+r 查找,替换1 双击shift 快速查找2 fi ...

  8. 聊天界面之进度条cell(一)

    ProgressCell用于显示文件传输的进度,困难点在于根据下载进度更新cell的进度条,先后尝试了几种方法: 1.有新的下载进度时,直接调用reloadData() 2.使用reloadRowsA ...

  9. java 获取项目绝对路径

    String classPath = Thread.currentThread().getContextClassLoader().getResource("").getPath( ...

  10. 【ubuntu】屏幕超时关闭后不能唤醒

    根据 http://blog.csdn.net/longshenlmj/article/details/18081167修改了"启动laptop_mode模式"gedit 的文件 ...