题意:

长度为nnn的序列,qqq次询问,每次给出lll、rrr,返回序列[l,r][l,r][l,r]中不同数的个数。(1≤n≤3∗104,1≤q≤2∗105)(1\leq n\leq 3*10^4,1\leq q\leq 2*10^5)(1≤n≤3∗104,1≤q≤2∗105)


思路:

与之前主席树的权值线段树思路不同,此题的思路是建立nnn颗线段树,第iii颗线段树存储区间[1,i][1,i][1,i]的信息。其中每个节点维护sumsumsum,表示节点对应区间中数的个数,因此每棵线段树中只保留每个数最后出现的位置。

举个例子,序列为555555\ 5\ 5\ 5\ 55 5 5 5 5,则第111颗线段树中只有第一个位置sumsumsum为111,然后第二颗线段树从第一颗线段树继承过来,由于555这个数字之前出现过,因此在第二颗线段树中令第一个位置的sumsumsum为000,令第二个位置的sumsumsum为111,来保存每个数字最后出现的位置。

因此查询区间[l,r][l,r][l,r]时,就在第rrr颗线段树中查询区间[l,n][l,n][l,n]中数的个数即可。


代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define LOG1(x1,x2) cout << x1 << ": " << x2 << endl;
#define LOG2(x1,x2,y1,y2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << endl;
#define LOG3(x1,x2,y1,y2,z1,z2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << " , " << z1 << ": " << z2 << endl;
typedef long long ll;
typedef double db;
const int N = 3*1e4+100;
const int M = 1e6+100;
const db EPS = 1e-9;
using namespace std;int n,a[N],q;
int ls[40*N],rs[40*N],sum[40*N],root[N],sz;
int pos[M]; //记录每个数的位置void build(int &now,int l,int r){if(!now) now = ++sz;if(l == r){sum[now] = 0; return;}build(ls[now],l,(l+r)>>1);build(rs[now],((l+r)>>1)+1,r);sum[now] = sum[ls[now]]+sum[rs[now]];
}void update(int x,int &now,int l,int r,int p1,int ct){if(!now) now = ++sz;if(l == r){sum[now] = sum[x]+ct; return;}int mid = (l+r)>>1;if(p1 <= mid){if(!rs[now]) rs[now] = rs[x]; //继承前一个备份的节点if(ls[now] <= now) ls[now] = 0; //因为现在要修改ls[now], 因此要重新开空间//如果ls[now] <= now, 表示这个节点是之前继承的, 因此要赋为0, 重新开空间update(ls[x],ls[now],l,mid,p1,ct);}else{if(!ls[now]) ls[now] = ls[x];if(rs[now] <= now) rs[now] = 0;update(rs[x],rs[now],mid+1,r,p1,ct);}sum[now] = sum[ls[now]]+sum[rs[now]];
}int ask(int &now,int l,int r,int p1){if(!now) now = ++sz;if(l >= p1) return sum[now];else if(r < p1) return 0;int mid = (l+r)>>1, ans = 0;if(mid >= p1) ans += ask(ls[now],l,mid,p1)+sum[rs[now]];else ans += ask(rs[now],mid+1,r,p1);return ans;
}int main()
{scanf("%d",&n);rep(i,1,n) scanf("%d",&a[i]);build(root[0],1,n);rep(i,1,n){if(pos[a[i]]){update(root[i-1],root[i],1,n,pos[a[i]],-1);update(root[i-1],root[i],1,n,i,1);pos[a[i]] = i;}else update(root[i-1],root[i],1,n,i,1), pos[a[i]] = i;}scanf("%d",&q);rep(i,1,q){int xx,yy; scanf("%d%d",&xx,&yy);printf("%d\n",ask(root[yy],1,n,xx));}return 0;
}

【SPOJ - DQUERY】D-query【主席树 —— 区间中不同数的个数】相关推荐

  1. HDU - 5919 Sequence II——主席树+区间种类++逆序建树

    [题目描述] HDU - 5919 Sequence II [题目分析] 题目给定一个数组,每次查询一个区间,找出区间内不同数字的个数x,然后输出按出现顺序第x/2向上取整个数字的位置. 按照要求,我 ...

  2. HDU 4348 To the moon(主席树区间修改)

    题意 给你一个区间,支持如下操作: 在一段区间内加上一个值,并生成一个历史版本 查询某个版本下一段区间内的和 回到一个历史版本上并舍弃之后的版本 做法 这就是主席树区间修改裸题啦QwQ 上一篇博客我讲 ...

  3. SPOJ DQUERY 求区间内不同数的个数 主席树

    这题跟HDU3333差不多吧. 离线的做法很简单,不再说了 以前做过. 主席树的做法就比较暴力了.. 什么是主席树呢.. 其实是某种称号. 在该题中的体现是可持久化的线段树. 对于一个数 如果以前没出 ...

  4. SPOJ DQUERY D-query(主席树 区间不同数个数)

    题意:问你区间有几个不同的数 思路:主席树nb.我们知道主席树每一个root都存着一棵权值线段树,现在我们在每个root中存位置,也就是01表示这个位置存不存在.然后我们用一个fa[a[i]]表示a[ ...

  5. HDU - 4348 To the moon(主席树区间更新-标记永久化)

    题目链接:点击查看 题目大意:给出一个初始时长度为 n 的序列,有 m 次操作,每种操作分为下列四种类型: C l r d:新建一个继承了前一个版本的数组,并将区间 [ l , r ] 内的数字都加上 ...

  6. HDU - 4348To the moon——主席树+区间修改

    HDU - 4348To the moon [题目描述] [题目分析] 题目中说明每次更新后时间都会加1,而且还会需要查询以前的区间,还会需要返回以前的时间,所以是很裸的主席树.区间查询的话我们同样需 ...

  7. CodeForces - 484E Sign on Fence(主席树区间合并+二分)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的数列,需要回答 mmm 次询问,每次询问的格式如下: lrkl\ r\ kl r k,需要回答区间 [l,r][l,r][l,r] 内,所有长度 ...

  8. PAT (Basic Level) Practise 1045 快速排序(离散化+主席树区间内的区间求和)

    1045. 快速排序(25) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CAO, Peng 著名的快速排序算法里有一个经典的划分 ...

  9. POJ 2104 K-th Number 主席树(区间第k大)

    题目链接: http://poj.org/problem?id=2104 K-th Number Time Limit: 20000MSMemory Limit: 65536K 问题描述 You ar ...

  10. ZOJ - 4117 BaoBao Loves Reading(树状数组求区间内不同数的个数+思维)

    题目链接:点击查看 题目大意:给出一个长度为 n 的序列,其意义为第 i 秒需要看第 a[ i ] 种书,书架上可以供应无限种书,但是书桌有容量,当书桌上的容量达到上限后,如果还想从书架上拿新书来看, ...

最新文章

  1. 后疫情时代:2021年商业科学改变供应链的5种方法
  2. Python性能测试
  3. win7 安装PyTorch
  4. Tomcat - 源码分析Tomcat是如何处理一个Servlet请求的
  5. linux usleep 线程控制权_linux多线程同步—信号量
  6. 使用纯索引子查询优化MySQL的分页查询速度
  7. Python批量复制文件
  8. Android开发笔记(九十七)图片的特效处理
  9. js截屏代码_服务端浏览器截屏
  10. 通向架构师的道路(第八天)之weblogic与apache的整合与调优 转
  11. html空间图片,html+js实现图片预览
  12. python制作简单计算器
  13. (java+selenium)Web自动化12306模拟人工滑块验证
  14. 使用Origin绘制弦图全流程
  15. 单片机控制NOKIA5110液晶屏之模块化编程
  16. node.js安装和vue全局安装教程
  17. vue结合videojs实现视频播放组件
  18. 求两个正整数的最大公约数
  19. iOS .tdb代替.dylib
  20. python distribute包管理工具安装AttributeError错误

热门文章

  1. 将ListT转化成 DataTable--调整可空类型的转化错误
  2. android service 的各种用法(IPC、AIDL)
  3. ASP.NET 分页技术
  4. java reactive web,基于RxJava的函数式Reactive Web框架:datamill
  5. 深入理解计算机系统第四版_技术干货 |深入理解计算机系统之链接
  6. php 图像居中裁剪函数,php中自定义图像居中裁剪函数实现的代码案例
  7. his提供哪些服务_品牌战略咨询能为企业提供哪些服务
  8. nyoj 16 矩形嵌套第七届河南省acm省赛H题
  9. 函数解素数求距离问题
  10. 【“新智认知”杯上海大学联赛】E-CSL的魔法(序列b到序列b‘需要的数据交换次数)