题目链接:

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. Spring Security学习笔记(一)

    认证和权限控制 AuthenticationManager是认证的主要接口,它只有一个authenticate方法,可以做3件事情. 返回一个认证信息(Authentication),表示认证成功 抛 ...

  2. eclipse 安装 lombok

    转载自http://bbs.itmayiedu.com/article/1527769518449 由于项目中有 @Slf4j 注解等,而 eclipse 需要安装 lombok 插件才能正常编译.由 ...

  3. JavaScript&jQuery 基本使用

    * 最近连续加班加点三周* 遭不住了 ...* 来点 js / jq 的货* 一个人撸PHP 撸HTML 撸CSS 撸JavaScript 撸jQuery* 不管有没有用记录一下** 1:jQuery ...

  4. Libcurl交叉编译

    目录 配置configure 执行make 取得su权限 开始安装 踩坑总结 配置configure ./configure --build=arm --host=mipsel-openwrt-lin ...

  5. 《JQuery常用插件教程》系列分享专栏

    <JQuery常用插件教程>已整理成PDF文档,点击可直接下载至本地查阅https://www.webfalse.com/read/201719.html 文章 使用jquery插件实现图 ...

  6. go字符串操作

    在Go语言标准库中的strings和strconv两个包可以对字符串做快速处理 string包 func Contains(s, substr string) bool 字符串s中是否包含substr ...

  7. python3.5 安装twisted

    https://blog.csdn.net/caimouse/article/details/77647952 下载地址:http://www.lfd.uci.edu/~gohlke/pythonli ...

  8. Python交换两个变量值的函数

    方法1:(错误) def func(a,b): a,b = b,a a = 1 b = 2 func(a,b) print(a," ",b) 方法2:(正确) def func(a ...

  9. Understanding Delegated JavaScript Events

    While I ended up using a CSS-only implementation for this pen, I started by writing it mostly using ...

  10. BZOJ1821_Group部落划分_KEY

    题目传送门 这是一道并查集的题目,相信很多人都看出来了. 用一个类似Kurskal的东西求出最近的最大值. 对于一些可以划分在同一个部落里的边,我们一定是优先选择短边合并. code: /****** ...