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中输出漂亮的表格
一.代码如下 二.输出效果如下 *&---------------------------------------------------------------------* *& ...
- 032-session函数
<?php $username="guest1"; if(isset($username)) { session_name($username); } echo " ...
- C# 借助CommandLine 写命令行工具 在数据库中创建job
首先需要用到 CommandLine.dll 提供两个下载链接,云盘是我自己上传的,也就是我在用的 http://commandline.codeplex.com/ https://pan.baid ...
- HZNU-ACM寒假集训Day11小结 贪心
1.刘汝佳紫书区间问题三大情况 1.选择不相交区间 贪心策略:一定要选择第一个区间 2.区间选点问题 贪心策略:取最后一个点 3.区间覆盖问题: n个闭区间,选择尽量少的区间覆盖一条指定线段[s,t] ...
- Apache部署Django+Vue
首先部署Vue,后端项目django开5000端口,所以vue里的路由是ip:5000,然后打包npm run build 生成dist文件 把dist文件里的index.html和static放在/ ...
- Redis Sentinel 学习笔记
转载出处: http://blog.csdn.net/lihao21 概述 Redis Sentinel 是用来实现 Redis 高可用的一套解决方案.Redis Sentinel 由两个部分组成:由 ...
- UVA - 12118 Inspector's Dilemma(检查员的难题)(欧拉回路)
题意:有一个n个点的无向完全图,找一条最短路(起点终点任意),使得该道路经过E条指定的边. 分析: 1.因为要使走过的路最短,所以每个指定的边最好只走一遍,所以是欧拉道路. 2.若当前连通的道路不是欧 ...
- UVA - 557 Burger(汉堡)(dp+概率)
题意:有n个牛肉堡和n个鸡肉堡给2n个孩子吃.每个孩子在吃之前都要抛硬币,正面吃牛肉堡,反面吃鸡肉堡.如果剩下的所有汉堡都一样,则不用抛硬币.求最后两个孩子吃到相同汉堡的概率. 分析: 1.先求最后两 ...
- C++基础--智能指针
智能指针其实也不是完全的指针,应该说是像指针一样的类对象,智能指针通常有指针的功能,当然同时也包含了一些额外的功能.目前比较常见的智能指针有auto_ptr.unique_ptr和shared_ptr ...
- python里的反射(自学习)
在做程序开发中,我们常常会遇到这样的需求:需要执行对象里的某个方法,或需要调用对象中的某个变量,但是由于种种原因我们无法确定这个方法或变量是否存在,这是我们需要用一个特殊的方法或机制要访问和操作这个未 ...