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. CSS3——选项卡切换

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. swift 定义类方法(type methed)

    swift   中声明结构体或者枚举的类型方法,需要在func前加上关键字 ststic  ,但是如果要定义一个类的类方法时,需要用关键字 class class SomeClass { class ...

  3. 数据结构与算法分析(2)——表、栈和队列

      抽象数据类型     抽象数据类型(ADT)是一系列操作的集合.诸如表.集合.图和他们的操作一起可以看做是抽象数据类型 表 List 表的实现有两种:数组和链表.数组实现的表在插入和删除操作上的花 ...

  4. logstash multiline 把文件处理为单个 event

    需求 多个文本文件需要存到 ES 中去. 每一个文件存放为一个 doc. 每一个文件都是多行的,行数不定,且没有固定的内容格式. update time: Mon Jun :: CST package ...

  5. Android打包失败Proguard returned with error code 1. See console

    问题一: [2013-06-28 11:12:10 - ] Proguard returned with error code 1. See console [2013-06-28 11:12:10 ...

  6. Android Dialog(对话框)

    一个对话框一般是一个出现在当前Activity之上的一个小窗口. 处于下面的Activity失去焦点, 对话框接受所有的用户交互. 对话框一般用于提示信息和与当前应用程序直接相关的小功能. Andro ...

  7. css扁平化博客学习总结(一)模块分析

    一.模块分析 1.每开发一个项目之前,首先要对项目进行一个大致规划,它到底要做什么功能,它有什么具体需求. 2.所以需要进行模块化分析,把这些东西具象化,把一个问题模块化,对需求有一个宏观的了解. 3 ...

  8. HTML招聘简历解析

    使用 jsoup 对 HTML 文档进行解析和操作 Jsoup解析html简历与dom4j解析xml是一个道理:首先必须知道html的格式,不知道格式,无法解析.根据格式,再将需要的内容通过下面的方法 ...

  9. Ext.Net学习笔记22:Ext.Net Tree 用法详解

    Ext.Net学习笔记22:Ext.Net Tree 用法详解 上面的图片是一个简单的树,使用Ext.Net来创建这样的树结构非常简单,代码如下: <ext:TreePanel runat=&q ...

  10. C 语言 查找一个字符串2在字符串1中出现的次数

    #include <stdio.h> #include <windows.h> int main() { ], b[]; char *temp; ; memset( a, ); ...