HDU 3333-Turing Tree-线段树+离散+离线
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
题目大意:
线段树的区间查询,查询区间内不同数值的数的和。
核心思想:
将数值离散化后记录每个数值a[i]最近一次出现的位置pre[a[i]]。
将查询离线处理,按查询区间的右端点排序,遍历原数组,依次进树,每进入一个数a[i],就将位置pre[a[i]]上的数清零,并更新pre[a[i]]=i。
代码如下:
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=3e4+20,Q=1e5+20;
ll a[N],b[N];
int pre[N],cnt;
struct tnode{
int l,r,id;
ll chu;
}que[Q];
struct node{
int l,r;
ll sum;
}tr[N<<2];
void pushup(int m)
{
tr[m].sum=tr[m<<1].sum+tr[m<<1|1].sum;
return;
}
void build(int m,int l,int r)
{
tr[m].l=l;
tr[m].r=r;
if(l==r)
{
tr[m].sum=0;
return;
}
int mid=(l+r)>>1;
build(m<<1,l,mid);
build(m<<1|1,mid+1,r);
pushup(m);
return;
}
void update(int m,int x,ll v)
{
if(tr[m].l==x&&tr[m].r==x)
{
tr[m].sum=v;
return;
}
int mid=(tr[m].l+tr[m].r)>>1;
if(x<=mid)
update(m<<1,x,v);
else
update(m<<1|1,x,v);
pushup(m);
return;
}
ll query(int m,int l,int r)
{
if(tr[m].l==l&&tr[m].r==r)
return tr[m].sum;
int mid=(tr[m].l+tr[m].r)>>1;
if(r<=mid)
return query(m<<1,l,r);
if(l>mid)
return query(m<<1|1,l,r);
return query(m<<1,l,mid)+query(m<<1|1,mid+1,r);
}
bool cmp1(tnode x,tnode y)
{
return x.r<y.r;
}
bool cmp2(tnode x,tnode y)
{
return x.id<y.id;
}
int getid(ll x)
{
return lower_bound(b+1,b+cnt,x)-b;
}
int main()
{
int T;
cin>>T;
while(T--)
{
int n,q;
cnt=1;
//输入
scanf("%d",&n);
for(int i=1;i<=n;i++)
pre[i]=0;
a[0]=-1;
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
//离散化
sort(a+1,a+1+n);
for(int i=1;i<=n;i++)
if(a[i]!=a[i-1])
b[cnt++]=a[i];
//建树
build(1,1,n);
//离线处理
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
scanf("%d%d",&que[i].l,&que[i].r);
que[i].id=i;
}
sort(que+1,que+1+q,cmp1);
que[0].r=0;
//更新和查询同时进行
for(int i=1;i<=q;i++)
{
for(int j=que[i-1].r+1;j<=que[i].r;j++)
{
int z=getid(a[j]);
if(pre[z])
update(1,pre[z],0);
update(1,j,a[j]);
pre[z]=j;
}
que[i].chu=query(1,que[i].l,que[i].r);
}
sort(que+1,que+1+q,cmp2);
//输出
for(int i=1;i<=q;i++)
printf("%lld\n",que[i].chu);
}
return 0;
}
HDU 3333-Turing Tree-线段树+离散+离线的更多相关文章
- HDU 3333 Turing Tree 线段树+离线处理
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Othe ...
- SPOJ D-query && HDU 3333 Turing Tree (线段树 && 区间不相同数个数or和 && 离线处理)
题意 : 给出一段n个数的序列,接下来给出m个询问,询问的内容SPOJ是(L, R)这个区间内不同的数的个数,HDU是不同数的和 分析 : 一个经典的问题,思路是将所有问询区间存起来,然后按右端点排序 ...
- HDU 3333 Turing Tree (线段树)
Turing Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- HDU 3333 Turing Tree(树状数组/主席树)
题意 给定一个长度为 \(n\) 的序列,\(m\) 个查询,每次查询区间 \([L,R]\) 范围内不同元素的和. \(1\leq T \leq 10\) \(1 \leq n\leq 300 ...
- HDU 3333 Turing Tree (主席树)
题意:给定上一个序列,然后有一些询问,求区间 l - r 中有多少个不同的数的和. 析:和求区间不同数的方法是一样,只要用主席树维护就好. 代码如下: #pragma comment(linker, ...
- hdu 3333 Turing Tree 图灵树(线段树 + 二分离散)
http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Others) ...
- HDU 3333 Turing Tree 离线 线段树/树状数组 区间求和单点修改
题意: 给一个数列,一些询问,问你$[l,r]$之间不同的数字之和 题解: 11年多校的题,现在属于"人尽皆知傻逼题" 核心思想在于: 对于一个询问$[x,R]$ 无论$x$是什么 ...
- HDU 3333 Turing Tree(离线树状数组)
Turing Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- hdu 3333 Turing Tree(线段树+离散化)
刚看到是3xian大牛的题就让我菊花一紧,觉着这题肯定各种高端大气上档次,结果果然没让我失望. 刚开始我以为是一个普通的线段树区间求和,然后啪啪啪代码敲完测试没通过,才注意到这个求和是要去掉相同的值的 ...
- HDU 3333 - Turing Tree (树状数组+离线处理+哈希+贪心)
题意:给一个数组,每次查询输出区间内不重复数字的和. 这是3xian教主的题. 用前缀和的思想可以轻易求得区间的和,但是对于重复数字这点很难处理.在线很难下手,考虑离线处理. 将所有查询区间从右端点由 ...
随机推荐
- devstack 使用openstack命令报错 The request you have made requires authentication. (HTTP 401) Missing value auth-url required for auth plugin password
关联错误: The request you have made requires authentication. (HTTP 401) (Request-ID: req-88ad2cba-0f2d-4 ...
- 2015-2016 ACM ICPC Baltic Selection Contest
这是上礼拜三的训练赛,以前做过一次,这次仅剩B题没补.题目链接:https://vjudge.net/contest/153192#overview. A题,水题. C题,树形DP,其实是一个贪心问题 ...
- HDU 1257 最少拦截系统 ——(LIS)
想了一下感觉和lis有关,交了果然AC.想不到很好的证明方法,试做证明如下:lis的每一个点都是一个不上升系统中的一员,设其为a[i],那么a[i-1]<a[i]肯定是成立的(lis的性质),夹 ...
- ROS机器人开发实践学习笔记3
摘要: 刚刚开始学习ROS,打算入机器人的坑了,参考教材是<ROS及其人开发实践>胡春旭编著 机械工业出版社 华章科技出品.本来以为可以按照书上的步骤一步步来,但是,too young t ...
- 单词拼接(dfs/回溯/递归)
单词拼接传送门 //单词拼接 #include<stdio.h> #include<string.h> #include<algorithm> using name ...
- Leetcode题目283.移动零(简单)
题目描述: 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序. 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明: 必须在原 ...
- Linux下expdp自动备份
创建sh脚本 [oracle@localhost backup]$ vi logicbackup.sh 添加脚本内容 #!/bin/sh # ############################# ...
- Qt configure 参数
在编译QT前,可加各种参数来定制自己想要的QT库.这对需要裁减QT库的朋友来说非常重要.对于如何编译QT,可以参考:http://hi.baidu.com/agassi%5Fp/blog/item/4 ...
- SpringBoot RestTemplate接收文件,并将文件发送到另外一个程序进行存储
最近有个需求,接收用户上报的证书,并且保存起来,证书大小不到1M,但该证书的保存必须在另外一个程序进行,所以想到使用springboot接收上传文件后,再通过RestTemplate将文件发送给另外一 ...
- 【English】What is a Java StringWriter, and when should I use it?(转帖)
转帖地址:http://www.it1352.com/989366.html Question: What is a Java StringWriter, and when should I use ...