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

这个题要求区间内不同值的和,一开始没有任何思路,看了题解,原来需要对查询进行离线操作。

因为需要求区间内互异值的和,对于一个固定的区间的话,自然只需要对于相同的值只留一个,其他置零即可。

但是对于动态的查询区间,保留的那个值的位置相对关键。

通过对查询的区间进行排序可以讲区间有序的排列(以区间的右端点递增排序)。

因为这样的话,对于这个数列,从第一个逐个插入,那么区间是[1, 1]->[1, 2]->[1, 3]……这样生成的,如果我们对于a[i],把之前出现过的a[i]都置零,这样此时对于已生成的区间[1, i],我们查询区间和[k, i]的时候(因为区间是按照右端点有序查询的),必然对于任意值p,都是先包含离i最近的那个p,才会包含前面的p,而前面的p已经被置零,故不会加入计算。而离i最近的p又会加入计算,不会影响结果。

所以这样边生成区间[1, i],边对于[k, i]区间查询。对于之前出现过的a[i]置零,便可以达到查询效果。当然最好输出的结果是按照题目要求的查询顺序输出的,这里采用了保存在sum数组中。

不过这里还有一点就是,如何对于之前的a[i]置零,此处采用了map,map里保存了最右端的a[i]的脚标,这样不断更新即可。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <string>
#define LL long long using namespace std; //线段树
//区间每点增值,求区间和
const int maxn = 30005;
struct node
{
int lt, rt;
LL val;
}tree[4*maxn]; //向上更新
void PushUp(int id)
{
tree[id].val = tree[id<<1].val + tree[id<<1|1].val;
} //建立线段树
void Build(int lt, int rt, int id)
{
tree[id].lt = lt;
tree[id].rt = rt;
tree[id].val = 0;//每段的初值,根据题目要求
if (lt == rt)
{
//tree[id].val = 1;
return;
}
int mid = (lt + rt) >> 1;
Build(lt, mid, id<<1);
Build(mid+1, rt, id<<1|1);
//PushUp(id);
} //更改区间内某个点的值
void Change(int lt, int rt, int id, int to)
{
if (lt <= tree[id].lt && rt >= tree[id].rt)
{
tree[id].val = to;
return;
}
int mid = (tree[id].lt + tree[id].rt) >> 1;
if (lt <= mid)
Change(lt, rt, id<<1, to);
if (rt > mid)
Change(lt, rt, id<<1|1, to);
PushUp(id);
} //查询某段区间内的he
LL Query(int lt, int rt, int id)
{
if (lt <= tree[id].lt && rt >= tree[id].rt)
return tree[id].val;
int mid = (tree[id].lt + tree[id].rt) >> 1;
LL ans = 0;
if (lt <= mid)
ans += Query(lt, rt, id<<1);
if (rt > mid)
ans += Query(lt, rt, id<<1|1);
return ans;
} struct qq
{
int from, to;
int id;
}q[100005]; bool cmp(qq a, qq b)
{
return a.to < b.to;
} int a[30005], n, m;
LL sum[100005]; void Work()
{
Build(1, n, 1);
map<int, int> s;
int t, now = 0;
for (int i = 1; i <= n; ++i)
{
t = s[a[i]];
if (t == 0)
{
Change(i, i, 1, a[i]);
s[a[i]] = i;
}
else
{
Change(t, t, 1, 0);
Change(i, i, 1, a[i]);
s[a[i]] = i;
}
for (;now < m && q[now].to == i; now++)
{
sum[q[now].id] = Query(q[now].from, q[now].to, 1);
}
}
} void Output()
{
for (int i = 0; i < m; ++i)
printf("%I64d\n", sum[i]);
} int main()
{
//freopen("test.in", "r", stdin);
int T;
scanf("%d", &T);
for (int times = 0; times < T; ++times)
{
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
scanf("%d", &m);
for (int i = 0; i < m; ++i)
{
scanf("%d%d", &q[i].from, &q[i].to);
q[i].id = i;
}
sort(q, q+m, cmp);
Work();
Output();
}
return 0;
}

ACM学习历程——HDU3333 Turing Tree(线段树 && 离线操作)的更多相关文章

  1. ACM学习历程—HDU 5289 Assignment(线段树 || RMQ || 单调队列)

    Problem Description Tom owns a company and he is the boss. There are n staffs which are numbered fro ...

  2. ACM学习历程—HDU 2795 Billboard(线段树)

    Description At the entrance to the university, there is a huge rectangular billboard of size h*w (h ...

  3. ACM学习历程——POJ3321 Apple Tree(搜索,线段树)

          Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will ...

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

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

  5. ACM学习笔记:可持久化线段树

    title : 可持久化线段树 date : 2021-8-18 tags : 数据结构,ACM 可持久化线段树 可以用来解决线段树存储历史状态的问题. 我们在进行单点修改后,线段树只有logn个(一 ...

  6. HDU 3333 Turing Tree (线段树)

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

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

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

  8. HDU3333 Turing Tree 离线树状数组

    题意:统计一段区间内不同的数的和 分析:排序查询区间,离线树状数组 #include <cstdio> #include <cmath> #include <cstrin ...

  9. HDU3333 Turing Tree(线段树)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=3333 Description After inventing Turing Tree, 3x ...

随机推荐

  1. jquery判断复选框是否被选中

    $("#isUse").click(function(){ if($(this).is(':checked')){ $(this).attr('checked','checked' ...

  2. 畅通project再续 HDU杭电1875 【Kruscal算法 || Prim】

    Problem Description 相信大家都听说一个"百岛湖"的地方吧.百岛湖的居民生活在不同的小岛中.当他们想去其它的小岛时都要通过划小船来实现.如今政府决定大力发展百岛湖 ...

  3. android 自定图库(转)

    githup: https://github.com/pengjianbo/GalleryFinal GalleryFinal简介 Android自定义相册,实现了拍照.图片选择(单选/多选). 裁剪 ...

  4. 基于红帽5裁剪一个简单的Linux

    HOST:宿主机 Target:目标机 1.基于HOST制作一个简单的可启动的Linux 1.给目标磁盘分区 两个: 在宿主机上:/dev/sdb1,/dev/sdb2 /dev/sdb1挂载到 /m ...

  5. 以python理解Linux的IO多路复用,select、poll、epoll

    题外话 之前在看Unix环境高级编程的时候,看完高级IO那一章,感觉自己萌萌哒,0.0 ,有点囫囵吞枣的感觉,之后翻了几篇博客,从纯系统的角度理解,稍微有了点概念,以这两篇为例,可以以后参考: htt ...

  6. 基于EasyNVR二次开发实现自己的摄像机IPC/NVR无插件化直播解决方案

    在之前的博客中<基于EasyNVR实现RTSP/Onvif监控摄像头Web无插件化直播监控>,我们已经比较多的描述EasyNVR所实现的功能,这些也在方案地址:http://www.eas ...

  7. wxPython的Refresh与事件双重响应

    #!/usr/bin/env python import wx class DoubleEventFrame(wx.Frame): def __init__(self, parent, id): wx ...

  8. 【题解】Fence(单调队列)

    [题解]Fence(单调队列) POJ - 1821 题目大意 有\(k\)个粉刷匠,每个粉刷匠一定要粉刷某个位置\(S_i\),一个粉刷匠可以粉刷至多\(l_i\)个位置(必须连续\(l_i\)互不 ...

  9. 【题解】[SCOI2010]股票交易

    十分普通的DP+不平凡的转移 传送门 这道题状态十分明显.转移是\(O(n^4)\)的,过不去,我们需要优化. 一个十分显然的DP是\(f(i,j)\)表示第\(i\)天时候拥有\(j\)单位股票的最 ...

  10. enumerate next eval reload 内置函数的用法

    enumerate next eval reload 内置函数的用法 #enumerate() 函数用于将一个可遍历的数据对象(如列表.元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用 ...