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教主的题. 用前缀和的思想可以轻易求得区间的和,但是对于重复数字这点很难处理.在线很难下手,考虑离线处理. 将所有查询区间从右端点由 ...
随机推荐
- 十二、 RAID
https://blog.51cto.com/sonlich http://note.youdao.com/noteshare?id=17083150f38dd19343f82ea6cc0e0e62& ...
- servlet 中session的使用方法(创建,使用)
创建: protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, ...
- ICEM—八分之一球(2D转3D)
原视频下载地址:https://yunpan.cn/cS3UPRtn5rVwY 访问密码 3d8d
- 【Python】使用Beautiful Soup等三种方式定制Jmeter测试脚本
背景介绍 我们在做性能调优时,时常需要根据实际压测的情况,调整线程组的参数,比如循环次数,线程数,所有线程启动的时间等. 如果是在一台Linux机器上,就免不了在本机打开图形页面修改,然后最后传递到压 ...
- MD5介绍
md5介绍 1. md5简介 md5的全称是md5信息摘要算法(英文:MD5 Message-Digest Algorithm ),一种被广泛使用的密码散列函数,可以产生一个128位(16字节,1字节 ...
- ArcGIS超级工具-征地部标准坐标导出导入 SPTOOLS
ArcGIS超级工具简称SPTOOLS 1.1征地部标准坐标导出 界面如下: 操作视频: https://weibo.com/tv/v/HvpNBrfeq?fid=1034:4374872936357 ...
- LC 987. Vertical Order Traversal of a Binary Tree
Given a binary tree, return the vertical order traversal of its nodes values. For each node at posit ...
- 深入理解Android插件化技术
深入理解Android插件化技术 转 https://zhuanlan.zhihu.com/p/33017826 插件化技术可以说是Android高级工程师所必须具备的技能之一,从2012年插件化概 ...
- c++ vector容器自增长
#include <iostream>#include <vector> using namespace std; int main(){ vector<int> ...
- 阶段5 3.微服务项目【学成在线】_day03 CMS页面管理开发_12-删除页面-服务端-接口开发
删除页面 api里面定义接口 返回类型是ReponseResult @ApiOperation("删除页面") public ResponseResult delete(Strin ...