SPOJ3267--D-query (主席树入门练习)
题意:查找区间内不同数字的个数。
两种做法,一种是 树状数组离线,另一种就是主席树。
树状数组离线操作的链接 http://www.cnblogs.com/oneshot/p/4110415.html
两种方法思路差不多,都是扫一遍,如果这个数曾经出现过那么就 在上次位置-1,如果没有出现过就在 当前位置+1,同时更新该数字的最新的位置。
这样的话,在主席树里面 以x为根的线段树存的就是1-x之间不同的数字的个数。我们只需要查找以r为根的线段树同时大于l的区间内的个数就行了。
给主席跪了,orz。主席树其实就是每个位置对应一颗线段树,但是这样 n 个点 n 棵线段树显然会MLE,怎么解决呢?我们可以看到 从第 i 棵线段树到第i+1 棵线段树,很多子树都是相同的,这样如果再重新建一棵完整的线段树显然浪费了很大的空间。我们只需要把第i棵线段树的 某个子树同时第i+1棵线段树 某个 节点下面即可,这样就大大减小了空间复杂度。
#include <map>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 3e4+;
int a[maxn],c[maxn*],lson[maxn*],rson[maxn*],tot,n,m;
int build(int l,int r)
{
int root = tot++;
c[root] = ;
if (l != r)
{
int mid = (l + r) >> ;
lson[root] = build(l,mid);
rson[root] = build(mid + ,r);
}
return root;
}
int update(int root,int pos,int val)
{
int newroot = tot++;
int tmp = newroot;
c[newroot] = c[root] + val;
int l = ,r = n;
while (l < r)
{
int mid = (l + r) >> ;
if (pos <= mid)
{
rson[newroot] = rson[root];
lson[newroot] = tot++;
newroot = lson[newroot];
root = lson[root];
r = mid;
}
else
{
lson[newroot] = lson[root];
rson[newroot] = tot++;
newroot = rson[newroot];
root = rson[root];
l = mid + ;
}
c[newroot] = c[root] + val;
}
return tmp;
}
int query(int root,int pos)
{
int res = ;
int l = ,r = n;
while (pos > l)
{
int mid = (l + r) >> ;
if (pos <= mid)
{
res += c[rson[root]];
root = lson[root];
r = mid;
}
else
{
root = rson[root];
l = mid + ;
}
}
return res + c[root];
}
int per_root[maxn];
int main(void)
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
while (~scanf ("%d",&n))
{
tot = ;
for (int i = ; i <= n ;i++)
scanf ("%d",a+i);
per_root[] = build(,n);
map<int,int>mp;
for (int i = ; i <= n; i++)
{
if (mp.find(a[i]) == mp.end())
{
per_root[i] = update(per_root[i-],i,);
}
else
{
int tmp = update(per_root[i-],mp[a[i]],-);
per_root[i] = update(tmp,i,);
}
mp[a[i]] = i;
}
scanf ("%d",&m);
for (int i = ; i < m; i++)
{
int l,r;
scanf ("%d%d",&l,&r);
printf("%d\n",query(per_root[r],l));
}
}
return ;
}
SPOJ3267--D-query (主席树入门练习)的更多相关文章
- 主席树入门(区间第k大)
主席树入门 时隔5个月,我又来填主席树的坑了,现在才发现学算法真的要懂了之后,再自己调试,慢慢写出来,如果不懂,就只会按照代码敲,是不会有任何提升的,都不如不照着敲. 所以搞算法一定要弄清原理,和代码 ...
- poj2104 k-th number 主席树入门讲解
poj2104 k-th number 主席树入门讲解 定义:主席树是一种可持久化的线段树 又叫函数式线段树 刚开始学是不是觉得很蒙逼啊 其实我也是 主席树说简单了 就是 保留你每一步操作完成之后 ...
- poj 2104 K-th Number (划分树入门 或者 主席树入门)
题意:给n个数,m次询问,每次询问L到R中第k小的数是哪个 算法1:划分树 #include<cstdio> #include<cstring> #include<alg ...
- POJ 2104&HDU 2665 Kth number(主席树入门+离散化)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 50247 Accepted: 17101 Ca ...
- EC Round 33 F. Subtree Minimum Query 主席树/线段树合并
这题非常好!!! 主席树版本 很简单的题目,给一个按照指定节点的树,树上有点权,你需要回答给定节点的子树中,和其距离不超过k的节点中,权值最小的. 肯定首先一想,按照dfs序列建树,然后按照深度为下标 ...
- CF893F Subtree Minimum Query 主席树
如果是求和就很好做了... 不是求和也无伤大雅.... 一维太难限制条件了,考虑二维限制 一维$dfs$序,一维$dep$序 询问$(x, k)$对应着在$dfs$上查$[dfn[x], dfn[x] ...
- 集训队8月1日(拓扑排序+DFS+主席树入门)
上午看书总结 今天上午我看了拓扑排序,DFS+剪枝,相当于回顾了一下,写了三个比较好的例题.算法竞赛指南93~109页. 1.状态压缩+拓扑排序 https://www.cnblogs.com/246 ...
- 主席树入门——询问区间第k大pos2104,询问区间<=k的元素个数hdu4417
poj2104找了个板子..,但是各种IO还可以进行优化 /* 找区间[l,r]第k大的数 */ #include<iostream> #include<cstring> #i ...
- A - 低阶入门膜法 - K-th Number (主席树查询区间第k小)
题目链接:https://cn.vjudge.net/contest/284294#problem/A 题目大意:主席树查询区间第k小. 具体思路:主席树入门. AC代码: #include<i ...
随机推荐
- JAVA/PHP/C#版RSA验签--转
本文是上一篇文章的兄弟篇,上篇文章介绍了客户端的sdk中如何基于JAVA/PHP/C#使用RSA私钥签名,然后服务端基于JAVA使用RSA公钥验签,客户端签名/服务端验签的模式只能帮助服务端检查客户端 ...
- Qt Sqlite封装类SqliteUtil
在网上找了很久关于Qt访问Sqlite数据库的封装类,但是没能找到一个很好的访问调用类,自己写了一个出来,在这里分享一下,希望能对大家有所帮助,小弟不才,写代码没多少经验,如果有什么不恰当之处,请批评 ...
- js window.open()弹出窗口参数说明及居中设置
window.open()可以弹出一个新的窗口,并且通过参数控制窗口的各项属性. 最基本的弹出窗口代码 window.open('httP://codeo.cn/'); window.open()各参 ...
- Java基础知识强化94:Calendar类之Calendar概述和获取日历字段的方法
1. Calendar类概述: Calendar 类是一个抽象类,它为特定瞬间与一组诸如 YEAR.MONTH.DAY_OF_MONTH.HOUR 等 日历字段之间的转换提供了一些方法,并 ...
- Sending Signals to Processes with kill, killall, and pkill
The Linux kernel allows many signals to be sent to processes. Use man 7 signals for a complete overv ...
- api接口
目录(?)[-] 接口特点汇总 PHP Token令牌 先说第一个tokenapi_token 服务端接口校验PHP实现流程如下 再说第二个tokenuser_token 接口用例如下 接口特点汇总: ...
- Maven 镜像
http://mvnrepository.com/http://search.maven.org/http://repository.sonatype.org/content/groups/publi ...
- ruby 知识点
$LOAD_PATH 执行 require 读取文件时搜索的目录名数组,也可以写作 $: 创建 URI 的时候可以直接这样 URI("http://www.dy2018.com/i/9751 ...
- Assembly 'Microsoft.Office.Interop.Excel
编译的时候报错,都无法通过编译: Assembly 'Microsoft.Office.Interop.Excel, Version=14.0.0.0, Culture=neutral, Public ...
- 安装VMware vCenter过程设置数据库方法
VMware vCenter自带免费版的SQL Server 2005 Express,但此免费版数据库适合于小于5台ESX主机的小型部署.如果规模较大可以单独安装数据库系统进行配置,这里选择我独立安 ...