HDU 3333 Turing Tree 线段树+离线处理
题目链接:
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 线段树+离线处理的更多相关文章
- SPOJ D-query && HDU 3333 Turing Tree (线段树 && 区间不相同数个数or和 && 离线处理)
题意 : 给出一段n个数的序列,接下来给出m个询问,询问的内容SPOJ是(L, R)这个区间内不同的数的个数,HDU是不同数的和 分析 : 一个经典的问题,思路是将所有问询区间存起来,然后按右端点排序 ...
- HDU 3333 Turing Tree (线段树)
Turing Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- HDU 3333 Turing Tree(树状数组/主席树)
题意 给定一个长度为 \(n\) 的序列,\(m\) 个查询,每次查询区间 \([L,R]\) 范围内不同元素的和. \(1\leq T \leq 10\) \(1 \leq n\leq 300 ...
- HDU 3333 Turing Tree (主席树)
题意:给定上一个序列,然后有一些询问,求区间 l - r 中有多少个不同的数的和. 析:和求区间不同数的方法是一样,只要用主席树维护就好. 代码如下: #pragma comment(linker, ...
- hdu 3333 Turing Tree 图灵树(线段树 + 二分离散)
http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Others) ...
- HDU 3333 Turing Tree 离线 线段树/树状数组 区间求和单点修改
题意: 给一个数列,一些询问,问你$[l,r]$之间不同的数字之和 题解: 11年多校的题,现在属于"人尽皆知傻逼题" 核心思想在于: 对于一个询问$[x,R]$ 无论$x$是什么 ...
- HDU 3333 Turing Tree(离线树状数组)
Turing Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- hdu 3333 Turing Tree(线段树+离散化)
刚看到是3xian大牛的题就让我菊花一紧,觉着这题肯定各种高端大气上档次,结果果然没让我失望. 刚开始我以为是一个普通的线段树区间求和,然后啪啪啪代码敲完测试没通过,才注意到这个求和是要去掉相同的值的 ...
- HDU 4288 Coder 【线段树+离线处理+离散化】
题意略. 离线处理,离散化.然后就是简单的线段树了.需要根据mod 5的值来维护.具体看代码了. /* 线段树+离散化+离线处理 */ #include <cstdio> #include ...
随机推荐
- 利用ascii码生成26个英文字母
<script> let a = ""; for (var i = 65; i < 91; i++) { a += String.fromCharCode(i); ...
- h5跳转到app的实现
随着业务的增加,可能存在这么一种需求,就是需要从h5中直接跳转到app.如果没有安装app的话,则提示到应用市场或者app store下载安装.不过问题就在这个地方,单纯的用h5是没有方法判断是否安装 ...
- python django-admin startproject django-admin命令未找到
在使用pip install安装django后使用django-admin生成项目失败解决办法 1.配置环境变量-在系统环境变量path添加后运行 D:\Program Files (x86)\pyt ...
- 第3天 Java基础语法
第3天 Java基础语法 今日内容介绍 引用数据数据类型(Scanner.Random) 流程控制语句(if.for.while.dowhile.break.continue) 引用数据类型 Scan ...
- 说一说MySQL的锁机制
锁概述 MySQL的锁机制,就是数据库为了保证数据的一致性而设计的面对并发场景的一种规则. 最显著的特点是不同的存储引擎支持不同的锁机制,InnoDB支持行锁和表锁,MyISAM支持表锁. 表锁就是把 ...
- 小程序开发-9-Behavior行为与加入缓存系统优化流行页面
Behavior行为与加入缓存系统优化流行页面 navi组件与移动端触碰区域探讨 触碰区域优化 设计师切图切大点,多余部分变成透明色 前端将可触碰区域变大 解决向左箭头变灰,向右变灰 禁用事件的技巧 ...
- 怎样才能使用ChipScope 加入被优化掉的信号
在调试过程中常常遇到的一个问题就是,xilinx工具在逻辑综合的过程中,将自己RTL代码中的很多变量都优化掉了,使得调试的抓信号的过程很纠结.以下是解决方法: 1.右键synthesis,在综合选项里 ...
- 【BZOJ4753】最佳团体(分数规划,动态规划)
[BZOJ4753]最佳团体(分数规划,动态规划) 题面 BZOJ Description JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号.方便起见,JYY的编号是0号.每个候选人都由一 ...
- day 4 集合
1.集合 In [1]: a = (11,22,33,11,22,33) In [2]: a Out[2]: (11, 22, 33, 11, 22, 33) #元组 In [3]: b = [11, ...
- 5 属性 property
1.属性 property 调用私有属性通过实例方法调用.达到这种效果 #property的作用:相当于把方法进行了封装, 开发者在对属性设置数据的时候更方便 class Dog(object): ...