SPOJ DQUERY D-query 离线+树状数组
本来是想找个主席树的题目来练一下的,这个题目虽说可以用主席树做,但是用这个方法感觉更加叼炸天
第一次做这种离线方法,所谓离线,就在把所有询问先存贮起来,预处理之后再一个一个操作
像这个题目,每个操作要求区间不同元素的个数,我盲目去查的话,某个元素在之前如果出现了,我把他算在当前区间也不好,算在之前的区间也不好,都会出错。
一个好的方法就是把区间排好序,针对某个区间在树状数组上更新以及查询相应值,这样能准确查出结果,但又不影响之后的查询
具体来说,先把区间按右端点进行排序(我一开始按左端点排,想错了),然后从小区间开始,然后树状数组的含义就是指以当前r为结尾的前缀区间的元素种类数,简单点说,就是我当前扫到l _ r区间,把l - r区间还没在树状数组上更新的值,更新一遍,在之前已经存在了的值先删掉再更新一遍,确保我确定的元素都是往r靠的,这样才能保证求取区间正确
比如我 1 2 2 1 3,当我r移到3的时候,加入前面的1还没在树状数组里更新过(但其实之前已经有读过1了)那就把之前的1的影响删掉,重新在这个3左边这个下标为4的位置给树状数组 add 1.这样确保之后不管我是查询 4 5 或者 1 5,元素1都只算了一次,但都没遗落(想想如果元素1一直在下标1那里,我查询4 5,就不会有1了)
总之:
所以这就是这个离线用法的妙处,尤其要理解树状数组在这个题目代表的含义是什么,即当前 以r结尾的区间的元素种类个数,为了维护这个值的准确性,必须把没出现过的,加入到树状数组中,之前已经出现过了并且再次出现的,以再次出现的位置为准。
每次对区间不用一开始就扫,每个就只要扫一次就可以了,用个map记录哪个出现了,出现在什么位置,就不用重新扫了,否则会超时,这样,总共也就扫了n下而不是n*q
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int N = 300010;
int n;
map<int,int>mp;
struct BIT
{
int c[N];
void init(int n)
{
for (int i=0;i<=n;i++) c[i]=0;
}
void add(int loc,int v)
{
while (loc<=n)
{
c[loc]+=v;
loc+=loc&(-loc);
}
}
int sum(int loc)
{
int ret=0;
while (loc){
ret+=c[loc];
loc-=loc&(-loc);
}
return ret;
}
}T;
struct node
{
int l,r,id;
bool operator <(const node&rhs) const{
//if (l==rhs.l) return r<rhs.r;
return r<rhs.r;
}
}query[1000000+10];
int ans[1000000+10];
int A[N];
int main()
{
while (scanf("%d",&n)!=EOF)
{
mp.clear();
T.init(n);
for (int i=1;i<=n;i++) scanf("%d",&A[i]);
int q;
scanf("%d",&q);
for (int i=0;i<q;i++)
{
scanf("%d%d",&query[i].l,&query[i].r);
query[i].id=i;
}
sort(query,query+q);
int cur=1;
for (int i=0;i<q;i++){
for (int j=cur;j<=query[i].r;j++){
if (mp.find(A[j])!=mp.end()){
T.add(mp[A[j]],-1);
}
T.add(j,1);
mp[A[j]]=j;
}
cur=query[i].r+1;
ans[query[i].id]=T.sum(query[i].r)-T.sum(query[i].l-1);
}
for (int i=0;i<q;i++){
printf("%d\n",ans[i]);
}
}
return 0;
}
SPOJ DQUERY D-query 离线+树状数组的更多相关文章
- HDU 5869 Different GCD Subarray Query 离线+树状数组
Different GCD Subarray Query Problem Description This is a simple problem. The teacher gives Bob a ...
- SPOJ DQUERY D-query (在线主席树/ 离线树状数组)
版权声明:本文为博主原创文章,未经博主允许不得转载. SPOJ DQUERY 题意: 给出一串数,询问[L,R]区间中有多少个不同的数 . 解法: 关键是查询到某个右端点时,使其左边出现过的数都记录在 ...
- SPOJ 3267 D-query(离散化+在线主席树 | 离线树状数组)
DQUERY - D-query #sorting #tree English Vietnamese Given a sequence of n numbers a1, a2, ..., an and ...
- SPOJ DQUERY - D-query (莫队算法|主席树|离线树状数组)
DQUERY - D-query Given a sequence of n numbers a1, a2, ..., an and a number of d-queries. A d-query ...
- CF #365 (Div. 2) D - Mishka and Interesting sum 离线树状数组
题目链接:CF #365 (Div. 2) D - Mishka and Interesting sum 题意:给出n个数和m个询问,(1 ≤ n, m ≤ 1 000 000) ,问在每个区间里所有 ...
- CF #365 (Div. 2) D - Mishka and Interesting sum 离线树状数组(转)
转载自:http://www.cnblogs.com/icode-girl/p/5744409.html 题目链接:CF #365 (Div. 2) D - Mishka and Interestin ...
- 13年山东省赛 Boring Counting(离线树状数组or主席树+二分or划分树+二分)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud 2224: Boring Counting Time Limit: 3 Sec ...
- hdu 4605 Magic Ball Game (在线主席树/离线树状数组)
版权声明:本文为博主原创文章,未经博主允许不得转载. hdu 4605 题意: 有一颗树,根节点为1,每一个节点要么有两个子节点,要么没有,每个节点都有一个权值wi .然后,有一个球,附带值x . 球 ...
- HDU - 4777 离线树状数组
离线树状数组搞一搞. #include<bits/stdc++.h> #define LL long long #define fi first #define se second #de ...
- 【BZOJ3653】谈笑风生 离线+树状数组+DFS序
[BZOJ3653]谈笑风生 Description 设T 为一棵有根树,我们做如下的定义: ? 设a和b为T 中的两个不同节点.如果a是b的祖先,那么称“a比b不知道高明到哪里去了”. ? 设a 和 ...
随机推荐
- isEqual判断相等性
1.isEqual方法用来判断两个比较者的内存地址是否一样.为了细分,有isEqualToString.isEqualToNumber.isEuqalToValue等,使用时一定要精确使用,比如虽然N ...
- 集合set 1
集合只能通过set() 函数进行创建 无序,不重复 每个元素必须是可哈希的,不可变类型(不可变数据类型在第一次声明赋值声明的时候, 会在内存中开辟一块空间, 用来存放这个变量被赋的值, 而 ...
- python面向对象之练习题2
练习题 需求: 士兵 可以 花钱买一个AK47 士兵 可以 用开开火 士兵 可以 买弹夹 士兵 可以 上子弹 士兵 可以 给 枪 添加子弹 枪 需要弹夹和有子弹的情况下,借助士兵扣动扳机 才能开火 枪 ...
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 表单:表单控件状态
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- Adroid ViewPage+GridView实现每页6个元素,三页滑动切换
//}//public class MainActivity extends Activity {// private static final float APP_PAGE_SIZE = 16.0f ...
- Outer()函数
转载:https://bbs.pinggu.org/thread-7078237-1-1.html R语言中的outer()函数,名为内积函数,但是他执行的功能并不是解析几何中的内积.那该函数到底发挥 ...
- Python django 安装 mysqlclient 失败
使用命令安装失败: C:\Program Files (x86)\Python\Python37-\Scripts>pip3..exe install mysqlclient Collectin ...
- 深度解析标点符号在Report写作中的应用
准确的标点符号和大写字母可以帮助Tutor准确理解report的意思.标点符号的某些方面,例如使用逗号,可以是一种个人风格,在引号中正确的标点符号是至关重要的.在前面的一些文章当中我们也给大家说了re ...
- SciPy 插值
章节 SciPy 介绍 SciPy 安装 SciPy 基础功能 SciPy 特殊函数 SciPy k均值聚类 SciPy 常量 SciPy fftpack(傅里叶变换) SciPy 积分 SciPy ...
- Centos7下 Oracle11G自动备份
1.创建备份目录: [root@Centos ~]# mkdir -p /home/oracle/backup 2.设置目录权限: [root@Centos ~]# chown -R oracle:o ...