Necklace HDU - 3874 (线段树/树状数组 + 离线处理)
Now Mery thinks the necklace is too long. She plans to take some continuous part of the necklace to build a new one. She wants to know each of the beautiful value of M continuous parts of the necklace. She will give you M intervals [L,R] (1<=L<=R<=N) and you must tell her F(L,R) of them.
InputThe first line is T(T<=10), representing the number of test cases.
For each case, the first line is a number N,1 <=N <=50000, indicating the number of the magic balls. The second line contains N non-negative integer numbers not greater 1000000, representing the beautiful value of the N balls. The third line has a number M, 1 <=M <=200000, meaning the nunber of the queries. Each of the next M lines contains L and R, the query.OutputFor each query, output a line contains an integer number, representing the result of the query.Sample Input
2
6
1 2 3 4 3 5
3
1 2
3 5
2 6
6
1 1 1 2 3 5
3
1 1
2 4
3 5
Sample Output
3
7
14
1
3
6
题意:给n个数字,代表项链每个单位的价值。在给m组查询,代表需要查询的[l,r]中的项链价值的总和;
项链区间价值的计算方法:区间中不同数字的和,即是该区间项链价值的总和。
做法:因为查询的区间已知,采用线段树/树状数组 + 离线查找的方法
将需要查找的区间根据 右端点 从小到大排序。从左往右逐步把数据加入到线段树中,当达到某一查询区间的右端点时,进行一次区间和的计算。
建立一个map数组,若某个数已经在序列中,则在最近出现的位置删除该数,这样就能保证每个数任意时刻只在线段树的中存储一次。
(举个栗子:如样例输入中 map[1] = 1,当第二个1放入线段树的时候,需要将第一个1清除,并更新map[1] = 2,以此保证线段树中该价值仅存在一个,
并且如果区间可以覆盖上一个map[1],那么区间必定可以覆盖现在的map[1]。)
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<string>
#include<set>
#include<stack>
#include<queue>
using namespace std;
const int maxn = ;
typedef long long ll;
struct node{
int l,r;
ll sum;
}tree[maxn];//建立线段树
ll T,n,m;
ll value[maxn],ans[maxn];// ans数组储存答案,value储存每个单位项链的价值
map<ll,int> mp;// 储存价值i在数组中最近出现的位置
struct node2
{
int l,r;
int index;//题目中要求的访问的顺序
}q[maxn]; void build(int rt,int left,int right){
tree[rt].l = left;
tree[rt].r = right;
tree[rt].sum = ;// 令每个根节点的值都为零,在计算的过程中再更新节点的值
if(left == right){
return;
}else{
int mid = (left + right)>>;
build(rt<<,left,mid);
build((rt<<)|, mid + , right);
}
}
void updata(int rt,int pos,ll val){//逐步将数据放入线段树中
tree[rt].sum += val;
if(tree[rt].l == tree[rt].r && tree[rt].l == pos){
return;
}
int mid = (tree[rt].l + tree[rt].r)>>;
if(pos <= mid){
updata(rt<<,pos,val);
}else{
updata((rt<<)|,pos,val);
}
}
ll query(int rt,int left,int right){
if(tree[rt].l == left && tree[rt].r == right){
return tree[rt].sum;
}
int mid = (tree[rt].l + tree[rt].r)>>;
if(right <= mid){
return query(rt<<,left,right);
}else if(left > mid){
return query((rt<<)| ,left ,right);
}else{
return query(rt<<,left,mid) + query((rt<<)| ,mid + ,right);
}
} bool cmp(node2 & a, node2 & b){//按照查询区间的右端点从小到大排序
return a.r < b.r;
}
int main(){
scanf("%lld",&T);
while(T--){
scanf("%lld",&n);
build(,,n);
mp.clear();
for(int i = ; i <= n ; i++){
scanf("%lld",&value[i]);
}
scanf("%lld",&m);
for(int i = ; i <= m ;i++){
scanf("%d %d",&q[i].l,&q[i].r);
q[i].index = i;
}
sort(q + , q + + m , cmp);
int id = ;//代表目前已经计算了几次题目想要查询的区间值
for(int i = ; i <= n ; i++){ updata(,i,value[i]);//按顺序从左到右将数组中的数据放入线段树中
if(mp[value[i]]) updata(,mp[value[i]],-value[i]); //如果价值value[i],将之前的数据进行删除,并将线段树更新
mp[value[i]] = i;// 更新value[i]最新出现的位置 while(id <= m && q[id].r == i){//当计算次数小于总次数,并且线段树对应下标等于某个查询区间的右端点时,进行一次查询
ans[q[id].index] = query(,q[id].l, q[id].r);
id++;
}
}
for(int i = ; i <= m ; i++){
printf("%lld\n",ans[i]);
}
}
return ;
}
线段树+离线处理做法
一个从很久以前就开始做的梦。
Necklace HDU - 3874 (线段树/树状数组 + 离线处理)的更多相关文章
- 2016 Multi-University Training Contest 5 1012 World is Exploding 树状数组+离线化
http://acm.hdu.edu.cn/showproblem.php?pid=5792 1012 World is Exploding 题意:选四个数,满足a<b and A[a]< ...
- SPOJ DQUERY树状数组离线or主席树
D-query Time Limit: 227MS Memory Limit: 1572864KB 64bit IO Format: %lld & %llu Submit Status ...
- D-query SPOJ 树状数组+离线
D-query SPOJ 树状数组+离线/莫队算法 题意 有一串正数,求一定区间中有多少个不同的数 解题思路--树状数组 说明一下,树状数组开始全部是零. 首先,我们存下所有需要查询的区间,然后根据右 ...
- HDU 4638 Group (线段树 | 树状数组 + 离线处理)
Group Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- Super Mario 树状数组离线 || 线段树
Super Mario Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- HDU 3333 - Turing Tree (树状数组+离线处理+哈希+贪心)
题意:给一个数组,每次查询输出区间内不重复数字的和. 这是3xian教主的题. 用前缀和的思想可以轻易求得区间的和,但是对于重复数字这点很难处理.在线很难下手,考虑离线处理. 将所有查询区间从右端点由 ...
- HDOJ 4417 - Super Mario 线段树or树状数组离线处理..
题意: 同上 题解: 抓着这题作死的搞~~是因为今天练习赛的一道题.SPOJ KQUERY.直到我用最后一种树状数组通过了HDOJ这题后..交SPOJ的才没超时..看排名...时间能排到11名了..有 ...
- HDU 5869 Different GCD Subarray Query 树状数组+离线
Problem Description This is a simple problem. The teacher gives Bob a list of problems about GCD (Gr ...
- HDU 4417 - Super Mario ( 划分树+二分 / 树状数组+离线处理+离散化)
题意:给一个数组,每次询问输出在区间[L,R]之间小于H的数字的个数. 此题可以使用划分树在线解决. 划分树可以快速查询区间第K小个数字.逆向思考,判断小于H的最大的一个数字是区间第几小数,即是答案. ...
随机推荐
- 六十、SAP中的加减乘除等算数运算符
一.代码和显示如下,很奇怪的事情是,负数的负号居然在数字后面
- 167-PHP 文本分割函数str_split(二)
<?php $str='PHP is a very good programming language'; //定义一个字符串 $arr=explode(' ',$str,-3); //使用空格 ...
- C# 并行线程调用
参考 一.异步委托开启线程 Action<int, int> a = add; a.BeginInvoke(, , null, null);//前两个是add方法的参数,后两个可以为空 C ...
- ubuntu18.04.2 hadoop3.1.2+zookeeper3.5.5高可用完全分布式集群搭建
ubuntu18.04.2 hadoop3.1.2+zookeeper3.5.5高可用完全分布式集群搭建 集群规划: hostname NameNode DataNode JournalNode Re ...
- oracle问题:char类型数据查询不到
select distinct id,name from test_table b where b.ID='001' ; id为char字段类型,使用该语句查询不出数据. 解决方法:加trim().改 ...
- Tornado的XSRF防范
XSRF XSRF即为跨站请求伪造 这个漏洞利用了浏览器的一个允许恶意攻击者在受害者网站注入脚本使未授权请求代表一个已登录用户的安全漏洞. 了解XSRF 当一个网站的图片SRC属性为另一个网站的链接时 ...
- 基础语法-选择结构switch
基础语法-选择结构switch 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Switch语句特点 switch语句选择的类型在jdk1.6只支持四种:byte,short,i ...
- EUI库 - 概述
新特性 36k 访问EUI组件宽高时,也会跟原生显示对象的表现一致,立即能得到包含子项的宽高值 统一的显示列表 普通对象和eui对象都可用addChild来添加 一个逻辑组件只管 ...
- cf 621E. Wet Shark and Blocks
神奇,矩阵乘法23333333333333333 递推式是很简单的(连我这种不会DP的人都写出来了.) 需要求出的是转移矩阵(还是叫系数矩阵的),也是最这个东西用快速幂. 这个东西的i,j大概就表示从 ...
- Python中的常用内置对象之range对象
range(start, stop[, step]) 可生成满足条件的数.具体来说是返回一个从start开始到小于stop的相邻数的差step的等差数列列表.结果中包含start一直到小于stop的 ...