HDU3874 线段树 + 离线处理
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3874 , 线段树(或树状数组) + 离线处理
下午做了第一道离线处理的题目(HDU4417),多少有点感觉,顺便就把这道题也给做了。
这道题就是要求某个区间内不重复数的和,自己在网上百度后参考别人的方法才AC的。参考来源:http://www.cnblogs.com/gj-Acit/p/3249827.html
这道题还是需要先离线处理数据,具体方法:
① 先用线段树把树给建立起来;
② 先把所有要查询的区间存起来,按照区间的右边界的大小从小到大排序,注意保存下标;
③ 对于排序后的每次询问要这样处理:把上次询问区间的右边界到当前询问的右边界中的这些数字进行处理,如果这些数字在之前出现过,则把之前出现的这个数字给删掉(置0即可),然后单点更新线段树;然后查询的话用线段树进行区间求和即可。
我参考的方法中是这样处理的,即用一个数组vis[]存储数字a[i]第一次出现的位置,后来扫描的时候如果发现 vis[a[i]] != i ,即说明该数字之前出现过。
最后注意这里用int储存结果会爆掉的,所以要用__int64.
#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
#include <string>
#include <string.h>
#include <algorithm>
using namespace std;
#define LL __int64
#define eps 1e-8
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int MOD = ;
const int maxn = + ;
const int N = + ;
LL sum[maxn << ] , ans[maxn << ]; //sum[]存线段树,ans[]存结果
int vis[N] , a[maxn]; //vis[]第一次出现的位置,a[]存储叶子节点信息
struct Section { //区间
int L , R;
int index;
bool operator < (const Section tmp) const {
return R < tmp.R;
}
} s[maxn << ];
void PushUp(int rt)
{
sum[rt] = sum[rt << ] + sum[rt << | ];
}
void build()
{
memset(sum , , sizeof(sum));
memset(vis , , sizeof(vis));
}
void update(int pos , int x , int l , int r , int rt)
{
if(l == r) {
sum[rt] = x;
return;
}
int m = (l + r) >> ;
if(pos > m)
update(pos , x , rson);
else
update(pos , x , lson);
PushUp(rt);
}
LL query(int L , int R , int l , int r , int rt)
{
if(L <= l && R >= r) {
return sum[rt];
}
int m = (l + r) >> ;
if(m < L)
return query(L , R , rson);
else if(m >= R)
return query(L , R , lson);
else
return query(L , R , lson) + query(L , R , rson);
}
int main()
{
int T , i , j , n , m;
cin >> T;
while(T--)
{
build();
scanf("%d" , &n);
for(i = ; i <= n ; i++) {
scanf("%d" , &a[i]);
if(!vis[a[i]]) //a[i]第一次出现的位置
vis[a[i]] = i;
update(i , a[i] , , n , ); //实际是在这里建的树
}
scanf("%d" , &m);
for(i = ; i <= m ; i++) {
scanf("%d %d" , &s[i].L , &s[i].R);
s[i].index = i;
}
sort(s + , s + m + );
for(i = , s[].R = ; i <= m ; i++) { //此为步骤③
for(j = s[i - ].R ; j <= s[i].R ; j++) {
if(vis[a[j]] != j) {
int tmp = vis[a[j]];
update(tmp , , , n , ); //删掉之前出现的该数字
vis[a[j]] = j; //删掉后再换位置
}
}
ans[s[i].index] = query(s[i].L , s[i].R , , n , );
}
for(i = ; i <= m ; i++)
printf("%I64d\n" , ans[i]);
}
return ;
}
HDU3874 线段树 + 离线处理的更多相关文章
- 线段树+离线 hdu5654 xiaoxin and his watermelon candy
传送门:点击打开链接 题意:一个三元组假设满足j=i+1,k=j+1,ai<=aj<=ak,那么就好的.如今告诉你序列.然后Q次询问.每次询问一个区间[l,r],问区间里有多少个三元组满足 ...
- 牛客练习赛53 E-老瞎眼pk小鲜肉(思维+线段树+离线)
前言 听说是线段树离线查询?? 做题做着做着慢慢对离线操作有点感觉了,不过也还没参透,等再做些题目再来讨论离线.在线操作. 这题赛后看代码发现有人用的树状数组,$tql$.当然能用树状数组写的线段树也 ...
- HDU 4638-Group(线段树+离线处理)
题意: 给n个编号,m个查询每个查询l,r,求下标区间[l,r]中能分成标号连续的组数(一组内的标号是连续的) 分析: 我们认为初始,每个标号为一个组(线段树维护区间组数),从左向右扫序列,当前标号, ...
- HDU 4630-No Pain No Game(线段树+离线处理)
题意: 给你n个数的序列a,q个询问,每个询问给l,r,求在下标i在[l,r]的区间任意两个数的最大公约数中的最大值 分析: 有了hdu3333经验,我们从左向右扫序列,如果当前数的约数在前面出现过, ...
- HDU 4288 Coder 【线段树+离线处理+离散化】
题意略. 离线处理,离散化.然后就是简单的线段树了.需要根据mod 5的值来维护.具体看代码了. /* 线段树+离散化+离线处理 */ #include <cstdio> #include ...
- SPOJ--K-query (线段树离线) 离线操作解决一些问题
K-query Given a sequence of n numbers a1, a2, ..., an and a number of k- queries. A k-query is a tri ...
- lca 欧拉序+rmq(st) 欧拉序+rmq(线段树) 离线dfs 倍增
https://www.luogu.org/problemnew/show/P3379 1.欧拉序+rmq(st) /* 在这里,对于一个数,选择最左边的 选择任意一个都可以,[left_index, ...
- 51nod 1463 找朋友(线段树+离线处理)
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1463 题意: 思路: 好题! 先对所有查询进行离线处理,按照右区间排序, ...
- 玲珑oj 1117 线段树+离线+离散化,laz大法
1117 - RE:从零开始的异世界生活 Time Limit:1s Memory Limit:256MByte Submissions:438Solved:68 DESCRIPTION 486到了异 ...
随机推荐
- 【转】webservice
一.WebService概念 Web Service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它 ...
- 业务、数据记录——ThreadPool.QueueUserWorkItem及Redis的实现
业务描述 当用户执行完业务操作,或者数据操作后,讲业务记录/数据追踪插入到Redis中.ThreadPool.QueueUserWorkItem定时检查队列并将上述数据插入到数据库中持久化. 实现流程 ...
- php用百度地图API进行逆地址解析
<?php /** * 根据地理坐标获取国家.省份.城市,及周边数据类(利用百度Geocoding API实现) * 百度密钥获取方法:http://lbsyun.baidu.com/apico ...
- 用RegularJS开发小程序 — mpregular解析
本文来自网易云社区. Mpregular 是基于 RegularJS(简称 Regular) 的小程序开发框架.开发者可以将直接用 RegularJS 开发小程序,或者将现有的 RegularJS 应 ...
- hdu2586(lca模板 / tarjan离线 + RMQ在线)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意: 给出一棵 n 个节点的带边权的树, 有 m 个形如 x y 的询问, 要求输出所有 x, ...
- 51nod1118(递推)
题目链接: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1118 题意: 中文题诶~ 思路: 因为机器人只能往下或者右 ...
- Mysql缓存的配置和使用
在mysql服务器高负载的情况下,必须采取一种措施给服务器减轻压力,减少服务器的I/O操作.一般采用的方法是优化sql操作语句,优化服务器的配置参数,从而提高服务器的性能.Mysql使用了几种内存缓存 ...
- shell脚本——循环和函数
1.打印一个等腰三角形 ` ;do -$i]` ;do echo -n ' ' done -]` ;do echo -n '*' done echo done 2.打印99乘法表 #!/bin/bas ...
- 阿里巴巴Java开发手册_不建议在循环体中使用+进行字符串拼接
18. [推荐]循环体内,字符串的连接方式,使用StringBuilder的append方法进行扩展. 说明:下例中,反编译出的字节码文件显示每次循环都会new出一个StringBuilder对象,然 ...
- Unity UGUI按钮添加点击事件
1. 可视化创建及事件绑定 # 1 : 通过 Hierarchy 面板创建 UI > Button. 2 : 创建一个脚本 TestClick.cs, 定义了一个 Click 的 public ...