[bzoj3524==bzoj2223][Poi2014]Couriers/[Coci 2009]PATULJCI——主席树+权值线段树
题目大意
给定一个大小为n,每个数的大小均在[1,c]之间的数列,你需要回答m个询问,其中第i个询问形如\((l_i, r_i)\),你需要回答是否存在一个数使得它在区间\([l_i,r_i]\)中出现至少\(\frac{r-l+1}{2}\)次。
题解
第一次写主席树。
不难发现,对于一个询问,只有可能要么有解,要么有一个解。
考虑到每个数均在一个确定的区间内,我们考虑开一棵权值线段树(以前一直用这种方法,但不知到这就是权值线段树)来记录每一个数字的出现次数。
考虑到他要求询问一个区间,我们只要知道在后一个时间点树的情况和前一个时间点的树的情况就好了。但是,我们需要修改线段树,所以我们需要使用一个可持久化数据结构来实现这种修改与查询。
具体地,我们考虑对于每次修改建一棵新树来存储这个时间点的情况。显然这个时间点可以从上一个时间点推出来。
如果我们真的建一棵新树,显然会爆空间。我们考虑仅仅在修改过的节点新建节点,同时把边乱连合理地连接即可。
对于每一个询问,我们二分答案即可。
至于复杂度,时间复杂度的话就是\(\Theta(跑得过)\),但空间复杂度就是\(\Theta(不一定能跑过)\)辣(逃
不过在bzoj改数据以后还是能过的。
注意
二分答案的时候,注意返回0的情况。也就是说,充分考虑到每一种情况并为其设立出口。
代码(bzoj3524)
#include <cstdio>
int n, m, sz;
const int maxn = 500010;
const int maxm = 10000010;
int rt[maxn], lc[maxm], rc[maxm], sum[maxm];
void update(int l, int r, int x, int &y, int v) {
y = ++sz;
sum[y] = sum[x] + 1;
if (l == r)
return;
lc[y] = lc[x];
rc[y] = rc[x];
int mid = (l + r) >> 1;
if (v <= mid)
update(l, mid, lc[x], lc[y], v);
else
update(mid + 1, r, rc[x], rc[y], v);
}
int que(int L, int R) {
int l = 1, r = n, mid, x, y, tmp = (R - L + 1) >> 1;
x = rt[L - 1];
y = rt[R];
while (l != r) {
if (sum[y] - sum[x] <= tmp)
return 0;
mid = (l + r) >> 1;
if (sum[lc[y]] - sum[lc[x]] > tmp) {
r = mid;
x = lc[x];
y = lc[y];
} else if (sum[rc[y]] - sum[rc[x]] > tmp) {
l = mid + 1;
x = rc[x];
y = rc[y];
} else
return 0;
}
return l;
}
int main() {
#ifdef D
freopen("input", "r", stdin);
#endif
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) {
int x;
scanf("%d", &x);
update(1, n, rt[i - 1], rt[i], x);
}
for (int i = 1; i <= m; i++) {
int l, r;
scanf("%d %d", &l, &r);
printf("%d\n", que(l, r));
}
}
代码(bzoj2223)
#include <cstdio>
int n, m, a, sz;
const int maxn = 500010;
const int maxm = 10000010;
int rt[maxn], lc[maxm], rc[maxm], sum[maxm];
void update(int l, int r, int x, int &y, int v) {
y = ++sz;
sum[y] = sum[x] + 1;
if (l == r)
return;
lc[y] = lc[x];
rc[y] = rc[x];
int mid = (l + r) >> 1;
if (v <= mid)
update(l, mid, lc[x], lc[y], v);
else
update(mid + 1, r, rc[x], rc[y], v);
}
int que(int L, int R) {
int l = 1, r = a, mid, x, y, tmp = (R - L + 1) >> 1;
x = rt[L - 1];
y = rt[R];
while (l != r) {
if (sum[y] - sum[x] <= tmp)
return 0;
mid = (l + r) >> 1;
if (sum[lc[y]] - sum[lc[x]] > tmp) {
r = mid;
x = lc[x];
y = lc[y];
} else if (sum[rc[y]] - sum[rc[x]] > tmp) {
l = mid + 1;
x = rc[x];
y = rc[y];
} else
return 0;
}
return l;
}
int main() {
#ifdef D
freopen("input", "r", stdin);
#endif
scanf("%d %d", &n, &a);
for (int i = 1; i <= n; i++) {
int x;
scanf("%d", &x);
update(1, a, rt[i - 1], rt[i], x);
}
scanf("%d", &m);
for (int i = 1; i <= m; i++) {
int l, r;
scanf("%d %d", &l, &r);
int ans = que(l, r);
if (ans > 0) {
printf("yes %d\n", ans);
} else
printf("no\n");
}
}
[bzoj3524==bzoj2223][Poi2014]Couriers/[Coci 2009]PATULJCI——主席树+权值线段树的更多相关文章
- 线段树(单标记+离散化+扫描线+双标记)+zkw线段树+权值线段树+主席树及一些例题
“队列进出图上的方向 线段树区间修改求出总量 可持久留下的迹象 我们 俯身欣赏” ----<膜你抄> 线段树很早就会写了,但一直没有总结,所以偶尔重写又会懵逼,所以还是要总结一下. ...
- [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树
二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...
- BZOJ2223[Coci 2009]PATULJCI——主席树
题目描述 输入 先输入一个数n,然后一个数表示这n个数中最大的是多少,接下来一行n个数.然后一个数m,最后m行询问每次两个数l,r. 输出 no或者yes+这个数 样例输入 10 3 1 2 1 2 ...
- HDU - 2665 Kth number 主席树/可持久化权值线段树
题意 给一个数列,一些询问,问$[l,r]$中第$K$大的元素是哪一个 题解: 写法很多,主席树是最常用的一种之一 除此之外有:划分树,莫队分块,平衡树等 主席树的定义其实挺模糊, 一般认为就是可持久 ...
- BZOJ2141排队——树状数组套权值线段树(带修改的主席树)
题目描述 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别 ...
- HDU6621 K-th Closest Distance 第 k 小绝对值(主席树(统计范围的数有多少个)+ 二分 || 权值线段树+二分)
题意:给一个数组,每次给 l ,r, p, k,问区间 [l, r] 的数与 p 作差的绝对值的第 k 小,这个绝对值是多少 分析:首先我们先分析单次查询怎么做: 题目给出的数据与多次查询已经在提示着 ...
- 莫队或权值线段树 或主席树 p4137
题目描述 有一个长度为n的数组{a1,a2,…,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. 输入格式 第一行n,m. 第二行为n个数. 从第三行开始,每行一个询问l,r. 输出格式 ...
- 权值线段树&&可持久化线段树&&主席树
权值线段树 顾名思义,就是以权值为下标建立的线段树. 现在让我们来考虑考虑上面那句话的产生的三个小问题: 1. 如果说权值作为下标了,那这颗线段树里存什么呢? ----- 这颗线段树中, 记录每个值出 ...
- 主席树 【权值线段树】 && 例题K-th Number POJ - 2104
一.主席树与权值线段树区别 主席树是由许多权值线段树构成,单独的权值线段树只能解决寻找整个区间第k大/小值问题(什么叫整个区间,比如你对区间[1,8]建立一颗对应权值线段树,那么你不能询问区间[2,5 ...
随机推荐
- Android TV 开发(3)
本文来自网易云社区 作者:孙有军 <LinearLayout android:id="@+id/input_num_line_3" and ...
- sed 集合(项目中的笔记)
奇数行和偶数行合并为一行: Like: Sequence number: 5398Sequence name: Glyma.16G123500.1Sequence number: 5399Sequen ...
- ABP框架设置默认语言
在Global.asax文件中设置 private readonly IAbpWebLocalizationConfiguration _webLocalizationConfiguration; p ...
- 剑指offer-调整数组顺序使奇数位于偶数前面13
题目描述 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变. class Solu ...
- spring mvc:实现给Controller函数传入list<pojo>参数
[1]前端js调用示例: ...insertStatisData?statisDatas=[{'cid':'2','devId':'9003','deviceName':'测试名','endTime' ...
- 【Python】Python内置函数dir详解
1.命令介绍 最近学习并使用了一个python的内置函数dir,首先help一下: 复制代码代码如下: >>> help(dir)Help on built-in function ...
- java对数组的操作
1 拷贝数组 数组全拷贝 数组定位拷贝 2 判断数组是否相等(每个元素都对应相等) 3 数组和集合的相互转化 import java.util.Arrays; import java.util.Lis ...
- htm,html,xhtml,xml,xsl,dhtml,shtm和shtml的区分
介绍一下htm,html,xhtml,xml,shtml的区分,以下内容来自百度后的知识整理. HTML和htm: HTML(Hypertext Markup Language)超文本传输语言,是ww ...
- LTE QOS
http://wenku.baidu.com/link?url=ziFIkdKaC7MU2RY-bTOp2bt87WFPw5_02bqmYs5W6w4ktOfPHEcWesK1U2T7YiyXjVSM ...
- 【EasyNetQ】- 请求回复
EasyNetQ还支持请求/响应消息传递模式.这使得实现客户端/服务器应用程序变得容易,客户端向服务器发出请求,然后服务器处理请求并返回响应.与传统的RPC机制不同,EasyNetQ请求/响应操作没有 ...