http://acm.hdu.edu.cn/showproblem.php?pid=3333

Turing Tree

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2614    Accepted Submission(s): 892

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
 
Author
3xian@GDUT
 
【题解】:

很不错的一道线段树题目,做了两天,终于给弄明白了。。。

看别人blog的时候,发现总是说离散化,,不明白什么意思。。。上网搜了下,其实就是一种思想的转化,,有时候我们一直在用,只不过不知道叫什么名字罢了。。。

比如对于这道题, 我们如果讨论一个数,判断它前面是否出现过,,因为0 ≤ Ai ≤ 1,000,000,000 ,很显然我们不能直接 用一个visit去判断。。

但是由于1 ≤ N ≤ 30,000 ,我们可以开一个30000的数组,然后把这些数存起来,排好序, 之后再判断一个数是否出现过的时候, 就可以用二分找到它的下标。。

对下表进行visit记录就可以了。。。

题意:  给出一个长度为N(N <= 30000)的数列,然后是一连串询问,询问数<= 100000,问给定区间内不同数字的和。

因为数字的范围较大,所以首先是对数列进行离散化,一般可以用二分或者hash,将大范围的数字映射到连续的区间。

然后一次性读入所有的区间(整数对),并且对整数对的右端点进行递增排序。这里注意,要记录下整数对读入的位置下标。。。

接下来按顺序枚举每个数字a[i],如果a[i]之前出现过,就将a[i]之前位置的值删除,然后在当前位置插入,当枚举的位置和区间对中某个位置相 等时执行询问操作。。。。

题解部分转自:http://www.cnblogs.com/183zyz/archive/2011/04/22/2025060.html

【code】:

 /**
judge status: Accepted exe.time:640ms
exe.memory 3696k language:C++
*/ #include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm> #define N 100010
#define M 30010 #define lson p<<1
#define rson p<<1|1 using namespace std; struct FTI{
int from,to,idx; //查询的始末位置 以及 索引位置
}fti[N]; struct Nod{
int l,r;
__int64 sum;
}node[M<<]; int temp[M],index[M],a[M],visit[M],k; __int64 ans[N]; bool cmp(FTI a,FTI b) //结构体排序调用函数
{
return a.to<b.to;
} void building(int l,int r,int p)
{
node[p].sum=;
node[p].l=l;
node[p].r=r;
if(l==r) return;
int mid=(l+r)/;
building(l,mid,lson);
building(mid+,r,rson);
} int findPos(int val) //二分查找值val在index中的位置
{
int l,r,mid;
l=;
r=k;
while(l<=r)
{
mid=(l+r)/;
if(index[mid]>val) r=mid-;
else if(index[mid]<val) l=mid+;
else return mid;
}
return -;
} void update(int id,int p,int val) //更新
{
if(node[p].l==node[p].r)
{
node[p].sum+=val;
return;
}
int mid = (node[p].l+node[p].r)>>;
if(id<=mid) update(id,lson,val);
else update(id,rson,val);
node[p].sum = node[lson].sum + node[rson].sum;
} __int64 Query(int l,int r,int p)
{
if(node[p].l==l&&node[p].r==r)
{
return node[p].sum;
}
int mid = (node[p].l+node[p].r)>>;
if(r<=mid) return Query(l,r,lson);
else if(l>mid) return Query(l,r,rson);
else return Query(l,mid,lson)+Query(mid+,r,rson);
} int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,i,j;
scanf("%d",&n);
for(i=;i<n;i++)
{
scanf("%d",a+i+);
temp[i]=a[i+];
}
sort(temp,temp+n);//排序
index[]=temp[];
j=;
for(i=;i<n;i++)
{
if(index[j]!=temp[i])
{
index[++j]=temp[i]; //消除重复数字
}
}
k=j;
memset(visit,,sizeof(visit));
int m;
scanf("%d",&m);
for(i=;i<=m;i++)
{
scanf("%d%d",&fti[i].from,&fti[i].to);
fti[i].idx = i;
}
sort(fti+,fti+m+,cmp); //结构体按to排序
building(,n,);
j=;
int id,pos;
for(i=;i<=n;i++)
{
id = findPos(a[i]);
pos = visit[id];
if(pos) update(pos,,-a[i]); //如果前面出现过a[i],则减掉前面的a[i]
update(i,,a[i]); //在i的位置增加a[i]
visit[id] = i; //标记出现过
while(j<=m&&i==fti[j].to)
{
ans[fti[j].idx] = Query(fti[j].from,fti[j].to,); //如果到了to的位置,就是需要统计的时候了,结果放到ans里面
j++;
}
}
for(i=;i<=m;i++)
{
printf("%I64d\n",ans[i]);
}
}
return ;
}

hdu 3333 Turing Tree 图灵树(线段树 + 二分离散)的更多相关文章

  1. HDU 3333 Turing Tree 线段树+离线处理

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Othe ...

  2. HDU 3333 Turing Tree (线段树)

    Turing Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  3. hdu 3333 Turing Tree(线段树+离散化)

    刚看到是3xian大牛的题就让我菊花一紧,觉着这题肯定各种高端大气上档次,结果果然没让我失望. 刚开始我以为是一个普通的线段树区间求和,然后啪啪啪代码敲完测试没通过,才注意到这个求和是要去掉相同的值的 ...

  4. SPOJ D-query && HDU 3333 Turing Tree (线段树 && 区间不相同数个数or和 && 离线处理)

    题意 : 给出一段n个数的序列,接下来给出m个询问,询问的内容SPOJ是(L, R)这个区间内不同的数的个数,HDU是不同数的和 分析 : 一个经典的问题,思路是将所有问询区间存起来,然后按右端点排序 ...

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

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

  6. HDU 3333 Turing Tree(离线树状数组)

    Turing Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  7. HDU 3333 Turing Tree(树状数组/主席树)

    题意 给定一个长度为 \(n​\) 的序列,\(m​\) 个查询,每次查询区间 \([L,R]​\) 范围内不同元素的和. \(1\leq T \leq 10\) \(1 \leq n\leq 300 ...

  8. HDU 4614 Vases and Flowers(线段树+二分)

    Vases and Flowers Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others ...

  9. hdu 5338 ZZX and Permutations (贪心+线段树+二分)

    ZZX and Permutations Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/O ...

随机推荐

  1. 主流存储引擎详解:Innodb,Tokudb、Memory、MYISAM、Federated

    主流存储引擎: Innodb:推荐使用,主力引擎,使用99%以上的场景 Tokudb:高速写入使用,日用量大量写入eg:500G可压缩为50G.适用于访问日志的写入,相对MYISAM有事务性,相对于I ...

  2. mapping 详解1(mapping type)

    映射(mapping) 映射是定义一个文档以及其所包含的字段如何被存储和索引的方法. 例如,用映射来定义以下内容: 哪些 string 类型的 field 应当被当成当成 full-text 字段 哪 ...

  3. angularjs学习总结一(表达式、指令、模型)

    一:自执行匿名函数 (function(){ /*code*/})();自执行匿名函数:常见格式:(function() { /* code */ })();解释:包围函数(function(){}) ...

  4. oracle学习总结2

    1:常用的函数 to_date()函数,将字符串转换为日期格式select to_date('2015-09-12','yyyy-MM-dd') from dual; --其中后面的日期格式要和前面要 ...

  5. 用expect做自动应答脚本

    Expect是一个用来实现自动交互功能的软件套件 (Expect [is a] software suite for automating interactive tools).使用它系统管理员可以创 ...

  6. #284 div.2 C.Crazy Town

    C. Crazy Town   Crazy Town is a plane on which there are n infinite line roads. Each road is defined ...

  7. 线程本地变量ThreadLocal

    一.本地线程变量使用场景 并发应用的一个关键地方就是共享数据.如果你创建一个类对象,实现Runnable接口,然后多个Thread对象使用同样的Runnable对象,全部的线程都共享同样的属性.这意味 ...

  8. mysql复习---仅涉及单表的操作

    一.登录数据库 二.创建数据库: 三.删除数据库 四.使用数据库创建表 五.向表中插入数据 六.查询 1.查询所有数据: 2.姓名查询 3.性别查询 4.查询姓名 5.根据年龄大小查询 6.多个条件查 ...

  9. plupload+struts2实现文件上传下载

    <%@ page language="java" import="java.util.*" pageEncoding="utf-8" ...

  10. 从V$SQL_PLAN中FORMAT执行计划

    10G版本 select sql_id from v$sqlarea where sql_text like'%xxx%'; select  * from v$sql_plan where sql_i ...