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. Objective-C /iphone开发基础:协议(protocol)

    protocol协议时为了补充Objective-C 只能单继承的缺陷而增加的一个新功能.Objective-C重所有的方法都是虚方法,所以在oc重也就没有关键字 virtual一说,有了协议可以补充 ...

  2. [转]Creating Unit Tests for ASP.NET MVC Applications (C#)

    本文转自:http://www.asp.net/mvc/tutorials/older-versions/unit-testing/creating-unit-tests-for-asp-net-mv ...

  3. C语言中 指针、引用和取值

    指针是一个存储计算机内存地址的变量.从指针指向的内存读取数据称作指针的取值.指针可以指向某些具体类型的变量地址,例如int.long和double.指针也可以是void类型.NULL指针和未初始化指针 ...

  4. Javascript做图片无缝平滑滚动

    因需要,google得到.作者不详.多谢.我这里略作修改.只是改变了ID. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitio ...

  5. 问题:loadrunner录制event为0

     loadrunner录制问题问题1:录制时出现event为0的状况 解决办法: 1.如果是IE浏览器,把启用第三方浏览器扩展*钩给去掉    2使用火狐浏览器,这个就比较好,在lr启动的时候就去勾选 ...

  6. CentOS 7 gedit编辑器中文乱码解决方法

    无需root登陆 打开终端输入如下命令: gsettings set org.gnome.gedit.preferences.encodings auto-detected "['GB180 ...

  7. li 水平排列并自动填满 ul

    找了li 如何水平排列并自动填满 ul,同时 li 宽度平均?资料,里面有提到"请用js动态计算保证兼容性", 因为我想实现的是,水平滚动条,ul的上级div是固定的宽度1000p ...

  8. NetBeans自定义代码折叠块,类似vs中的#region

    //<editor-fold defaultstate="collapsed" desc="测试代码折叠"> echo '<script ty ...

  9. 程序员,一起玩转GitHub版本控制,超简单入门教程 干货2

    本GitHub教程旨在能够帮助大家快速入门学习使用GitHub,进行版本控制.帮助大家摆脱命令行工具,简单快速的使用GitHub. 做全栈攻城狮-写代码也要读书,爱全栈,更爱生活. 更多原创教程请关注 ...

  10. IE, FF, Safari前端开发常用调试工具

    一些前端开发 IE 中的常用调试工具: Microsoft Script Debugger —— Companion.JS need to install this Companion.JS —— J ...