ACM学习历程——HDU3333 Turing Tree(线段树 && 离线操作)
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.
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).
这个题要求区间内不同值的和,一开始没有任何思路,看了题解,原来需要对查询进行离线操作。
因为需要求区间内互异值的和,对于一个固定的区间的话,自然只需要对于相同的值只留一个,其他置零即可。
但是对于动态的查询区间,保留的那个值的位置相对关键。
通过对查询的区间进行排序可以讲区间有序的排列(以区间的右端点递增排序)。
因为这样的话,对于这个数列,从第一个逐个插入,那么区间是[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(线段树 && 离线操作)的更多相关文章
- ACM学习历程—HDU 5289 Assignment(线段树 || RMQ || 单调队列)
Problem Description Tom owns a company and he is the boss. There are n staffs which are numbered fro ...
- ACM学习历程—HDU 2795 Billboard(线段树)
Description At the entrance to the university, there is a huge rectangular billboard of size h*w (h ...
- ACM学习历程——POJ3321 Apple Tree(搜索,线段树)
Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will ...
- HDU 3333 Turing Tree 线段树+离线处理
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Othe ...
- ACM学习笔记:可持久化线段树
title : 可持久化线段树 date : 2021-8-18 tags : 数据结构,ACM 可持久化线段树 可以用来解决线段树存储历史状态的问题. 我们在进行单点修改后,线段树只有logn个(一 ...
- HDU 3333 Turing Tree (线段树)
Turing Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- SPOJ D-query && HDU 3333 Turing Tree (线段树 && 区间不相同数个数or和 && 离线处理)
题意 : 给出一段n个数的序列,接下来给出m个询问,询问的内容SPOJ是(L, R)这个区间内不同的数的个数,HDU是不同数的和 分析 : 一个经典的问题,思路是将所有问询区间存起来,然后按右端点排序 ...
- HDU3333 Turing Tree 离线树状数组
题意:统计一段区间内不同的数的和 分析:排序查询区间,离线树状数组 #include <cstdio> #include <cmath> #include <cstrin ...
- HDU3333 Turing Tree(线段树)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=3333 Description After inventing Turing Tree, 3x ...
随机推荐
- 【甘道夫】Ubuntu14 server + Hadoop2.2.0环境下Sqoop1.99.3部署记录
第一步.下载.解压.配置环境变量: 官网下载sqoop1.99.3 http://mirrors.cnnic.cn/apache/sqoop/1.99.3/ 将sqoop解压到目标文件夹,我的是 /h ...
- Android推断是否有sd卡
推断手机上是否有SD卡存在.作为经常用法,写到工具类里,用时直接调用.代码例如以下: public static boolean hasSdcard(){ String state = Environ ...
- 网络工具的瑞士军刀netcat
这是一个聒噪的夜晚,假设要给出个原因.可能是由于尽管我认为西班牙不纯粹,可是怎么也不至于干为人家搭台面自己不唱戏的角色吧..结束以后.我认为该玩一下素有网络瑞士军刀之称谓的netcat了. 尽管瑞士军 ...
- hashCode与equals的作用与区别及应当注意的细节
最近去面试了几家公司,被问到hashCode的作用,虽然回答出来了,但是自己还是对hashCode和equals的作用一知半解的,所以决定把它们研究一下. 以前写程序一直没有注意hashCode的作用 ...
- 2009-04-19 22:40 SQL SERVER游标的讲解
游标和游标的优点 在数据库中,游标是一个十分重要的概念.游标提供了一种对从表中检索出的数据进行操作的灵活手段,就本质而言,游标实际上是一种能从包括多条数据记录的结 果集中每次提取一条记录的机制.游标总 ...
- OpenCV 入门示例之三:AVI 视频播放控制
前言 在前文中给出了一个非常简短的视频播放程序,但它没有实现常规视频播放器中的播放滚动条功能,本文对此视频播放器程序加以改进,实现此功能. 滚动条的实现思路 滚动条的功能实质上就是从一帧跳跃到另外一帧 ...
- WPF实现带全选复选框的列表控件
本文将说明如何创建一个带全选复选框的列表控件.其效果如下图: 这个控件是由一个复选框(CheckBox)与一个 ListView 组合而成.它的操作逻辑: 当选中“全选”时,列表中所有的项目都会被选中 ...
- ASP.NET动态网站制作(10)-- JQ(2)
前言:jq的第二节课. 内容: 1.管理选择结果: (1)获取元素个数:$("img").size():获取页面中所有“img”个数: (2)提取元素:$("img[ ...
- Webpack探索【12】--- externals详解
本文主要讲externals相关内容. https://segmentfault.com/a/1190000012113011
- UVa 10828 Back to Kernighan-Ritchie 高斯消元+概率DP
题目来源:UVa 10828 Back to Kernighan-Ritchie 题意:从1開始 每次等概率从一个点到和他相邻的点 有向 走到不能走停止 求停止时每一个点的期望 思路:写出方程消元 方 ...