题目大意

给定一个大小为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——主席树+权值线段树的更多相关文章

  1. 线段树(单标记+离散化+扫描线+双标记)+zkw线段树+权值线段树+主席树及一些例题

    “队列进出图上的方向 线段树区间修改求出总量 可持久留下的迹象 我们 俯身欣赏” ----<膜你抄>     线段树很早就会写了,但一直没有总结,所以偶尔重写又会懵逼,所以还是要总结一下. ...

  2. [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树

    二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...

  3. BZOJ2223[Coci 2009]PATULJCI——主席树

    题目描述 输入  先输入一个数n,然后一个数表示这n个数中最大的是多少,接下来一行n个数.然后一个数m,最后m行询问每次两个数l,r. 输出 no或者yes+这个数 样例输入 10 3 1 2 1 2 ...

  4. HDU - 2665 Kth number 主席树/可持久化权值线段树

    题意 给一个数列,一些询问,问$[l,r]$中第$K$大的元素是哪一个 题解: 写法很多,主席树是最常用的一种之一 除此之外有:划分树,莫队分块,平衡树等 主席树的定义其实挺模糊, 一般认为就是可持久 ...

  5. BZOJ2141排队——树状数组套权值线段树(带修改的主席树)

    题目描述 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家 乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别 ...

  6. HDU6621 K-th Closest Distance 第 k 小绝对值(主席树(统计范围的数有多少个)+ 二分 || 权值线段树+二分)

    题意:给一个数组,每次给 l ,r, p, k,问区间 [l, r] 的数与 p 作差的绝对值的第 k 小,这个绝对值是多少 分析:首先我们先分析单次查询怎么做: 题目给出的数据与多次查询已经在提示着 ...

  7. 莫队或权值线段树 或主席树 p4137

    题目描述 有一个长度为n的数组{a1,a2,…,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. 输入格式 第一行n,m. 第二行为n个数. 从第三行开始,每行一个询问l,r. 输出格式 ...

  8. 权值线段树&&可持久化线段树&&主席树

    权值线段树 顾名思义,就是以权值为下标建立的线段树. 现在让我们来考虑考虑上面那句话的产生的三个小问题: 1. 如果说权值作为下标了,那这颗线段树里存什么呢? ----- 这颗线段树中, 记录每个值出 ...

  9. 主席树 【权值线段树】 && 例题K-th Number POJ - 2104

    一.主席树与权值线段树区别 主席树是由许多权值线段树构成,单独的权值线段树只能解决寻找整个区间第k大/小值问题(什么叫整个区间,比如你对区间[1,8]建立一颗对应权值线段树,那么你不能询问区间[2,5 ...

随机推荐

  1. Spring研磨分析、Quartz任务调度、Hibernate深入浅出系列文章笔记汇总

    Spring研磨分析.Quartz任务调度.Hibernate深入浅出系列文章笔记汇总 置顶2017年04月27日 10:46:45 阅读数:1213 这系列文章主要是对Spring.Quartz.H ...

  2. 【BZOJ 1269】文本编辑器

    题目 这些日子,可可不和卡卡一起玩了,原来可可正废寝忘食的想做一个简单而高效的文本编辑器.你能帮助他吗?为了明确任务目标,可可对"文本编辑器"做了一个抽象的定义: Move k:将 ...

  3. Ubuntu 首次给root用户设置密码

    用过ubuntu的人都知道,刚安装好root用户是没有密码的,没有密码我们就没法用root用户登录.给root用户设置密码输入命令sudo passwd root,然后系统会让你输入密码,这时输入的密 ...

  4. 解析车辆VIN码识别(车架号识别)系统

    很多人在购买车辆的时候,只关注性能.外观.内饰等,其实真正的内行是首先看车辆的VIN码,也叫车架号码. VIN码(车架号码)是一辆车的唯一身份证明,一般在车辆的挡风玻璃处,有的在车辆防火墙上,或B柱铭 ...

  5. 常见bug解析-移动端

    手机测试常见bug解析 1.测试时遇到“手机无响应”? 有以下几个原因: a.手机内存不足 b.android进程之间死锁引起的(就是两个进程之间) c.手机的CPU运行高引起的 可以查看手机的崩溃日 ...

  6. Java IO学习--输入输出流

    一.Java IO的定义 I/O:输入输出系统,由输入输出控制系统和外围设备两部分组成. Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输 ...

  7. 为什么logstash进程的CPU使用率100%?

    机器上有个进程cpu使用率很高,近100%了, Tasks: 120 total, 2 running, 118 sleeping, 0 stopped, 0 zombie%Cpu(s): 99.0 ...

  8. SPFA模板 Bellmanford优化版

    SPFA模板: queue<int>Q; ]; ],sumv[]; *],__next[*],e,w[*],first[],cnts[]; void AddEdge(int U,int V ...

  9. NO9——线段相关

    #include <stdio.h> #include <iostream> #include <math.h> #include <algorithm> ...

  10. javascript中的大括号和中括号

    文章:javascript中{},[]中括号,大括号的含义和使用