题目链接:

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)
#### 问题描述
> 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.
#### 输入
> 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).
#### 输出
> 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

题意

求一段区间的所有不同的数字的和。

题解

这题要考虑离线处理查询。

有多个相同的数字这么办?

我们可以考虑在每个时刻,我们插入的数据都是不同的,我们可以从左到右插入一个数据的时候,我们先判断一下它是否已经插入过了,如果已经插入了我们就把之前的位置的那个数删点,同时插入现在这个位置(相等于是往右边转移了这个数),同时我们吧查询按照右端点升序排,先处理右端点比较小的查询,这样就能保证正确性了。

代码

#include<iostream>
#include<cstdio>
#include<map>
#include<algorithm>
#include<cstring>
#define lson (o<<1)
#define rson ((o<<1)|1)
#define M l+(r-l)/2
using namespace std; const int maxn = 3e4 + 10;
const int maxq = 1e5 + 10;
typedef long long LL; LL sumv[maxn << 2];
map<int, int> mp; int arr[maxn];
LL ans[maxq]; struct Node {
int l, r, id;
bool operator <(const Node& tmp) const {
return r < tmp.r;
}
}nds[maxq]; int ql, qr;
LL _sumv;
void query(int o, int l, int r) {
if (ql <= l&&r <= qr) {
_sumv += sumv[o];
}
else {
if (ql <= M) query(lson, l, M);
if (qr>M) query(rson, M + 1, r);
}
} int _p, _v;
void update(int o, int l, int r) {
if (l == r) {
sumv[o] = _v;
}
else {
if (_p <= M) update(lson, l, M);
else update(rson, M + 1, r);
sumv[o] = sumv[lson] + sumv[rson];
}
} int n; void init() {
memset(sumv, 0, sizeof(sumv));
mp.clear();
} int main() {
int tc;
scanf("%d", &tc);
while (tc--) {
init();
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &arr[i]);
}
int q; scanf("%d", &q);
for (int i = 0; i < q; i++) {
scanf("%d%d", &nds[i].l, &nds[i].r);
nds[i].id = i;
}
sort(nds, nds + q);
int pos = 1;
for (int i = 0; i < q; i++) {
int l = nds[i].l, r = nds[i].r, id = nds[i].id;
while (pos <= r) {
if (mp.count(arr[pos])) {
_p = mp[arr[pos]], _v = 0;
update(1, 1, n);
}
mp[arr[pos]] = pos;
_p = pos, _v = arr[pos];
update(1, 1, n);
pos++;
}
ql = l, qr = r; _sumv = 0;
query(1, 1, n);
ans[id] = _sumv;
}
for (int i = 0; i < q; i++) {
printf("%lld\n", ans[i]);
}
}
return 0;
}

乱七八糟

对于一个区间里面的相同的数字,是我们不想要的,我们要达到的目的就是要去除它们的影响,删除它们是一种不错的解决办法,那么我们对于一个出现多次的数,就只要保留一个,保留哪一个呢?第一个想到的自然是最左边和最右边,而之后调整区间的操作,也是完全为了配合我们删除插入顺序对结果的影响而做出的调整。

之前也有类似的,如用数状数组计算排名,对于比它大的数,是我们不想要的,插入它的时候,我们只需要知道比它小的数有多少个,一种解决方案就是给每个数据按从小到大从左到右先安个空位置,插入的时候对号入座,那比当前插入的数小的自然就会跑到左边,我们可以用树状数组或线段树来维护。

离线处理一个比在线做的优势就是!!!我们能!调整!处理的顺序!

HDU 3333 Turing Tree 线段树+离线处理的更多相关文章

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

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

  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(树状数组/主席树)

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

  4. HDU 3333 Turing Tree (主席树)

    题意:给定上一个序列,然后有一些询问,求区间 l - r 中有多少个不同的数的和. 析:和求区间不同数的方法是一样,只要用主席树维护就好. 代码如下: #pragma comment(linker, ...

  5. hdu 3333 Turing Tree 图灵树(线段树 + 二分离散)

    http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Others)    ...

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

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

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

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

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

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

  9. HDU 4288 Coder 【线段树+离线处理+离散化】

    题意略. 离线处理,离散化.然后就是简单的线段树了.需要根据mod 5的值来维护.具体看代码了. /* 线段树+离散化+离线处理 */ #include <cstdio> #include ...

随机推荐

  1. H3C Telnet 配置-01

    Telnet 配置管理方法是网络工程师和网络管理员使用最广泛的一种设备访问控制方法,它通过局域网或广域网实现本地或远程的访问控制,但是它的实验必须要求首先对设备进行初始化配置,否则用户无法正常登录和访 ...

  2. redis安装make失败,make[1]: *** [adlist.o] Error 127....

    解压后 执行make后报错: cd src && make all make[1]: Entering directory `/home/liuchaofan/redis-3.0.7/ ...

  3. Canvas路径方向

    使用Canvas路径画图需要注意方向,画图方向是顺时针还是逆时针需要记住.下面让我们看看Canvas常见路径方向. arc 参数值 context.arc(x,y,r,sAngle,eAngle,co ...

  4. vue-cli 3.0 使用axios配置跨域访问豆瓣接口

    vue-cli 3.0 配置axios跨域访问豆瓣接口 自己做的小demo 由于豆瓣api跨域问题,因此不能直接通过ajax请求访问,我们通过vue-cli提供给我们的代理 进行配置即可, 在根目录下 ...

  5. QQ好友的价值玩法 及如何搞到几万好友?

    我们知道,现在的自媒体平台太多了.微信公众号,企鹅媒体平台,今日头条.搜狐.UC.一点等等等. 但是现在的话最主要的就是盈利,我们很多朋友玩自媒体这个在很多平台都有自己的账号和大量的粉丝.但是,最后大 ...

  6. HTTP学习之URL与资源

    URL是因特网资源的标准化名称,该字符串指向一条电子信息片段,定义服务端应用程序在什么位置以及客户端要如何与其交互 一条完整的URL由多个片段组成. 通用URL组件 方案 以哪种协议访问服务器 用户 ...

  7. SpaceVim 语言模块 elm

    原文连接: https://spacevim.org/cn/layers/lang/elm/ 模块简介 功能特性 依赖安装及启用模块 依赖安装 启用模块 快捷键 语言专属快捷键 交互式编程 模块简介 ...

  8. shiro中基于注解实现的权限认证过程

    授权即访问控制,它将判断用户在应用程序中对资源是否拥有相应的访问权限. 如,判断一个用户有查看页面的权限,编辑数据的权限,拥有某一按钮的权限等等. 一.用户权限模型 为实现一个较为灵活的用户权限数据模 ...

  9. 北京Uber优步司机奖励政策(2月29日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  10. 北京Uber优步司机奖励政策(10月26日~11月1日)

    用户组:优步北京人民优步A组(适用于10月26日-11月1日) 滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/ ...