BZOJ 3524 [Poi2014]Couriers 可持久化线段树

题意:链接

方法:可持久化线段树。

解析:

可持久化数据结构好神啊,感觉都好玄妙的感觉。

首先建树的目的就是建立一棵权值树,维护的是在L,R里某些权值的数的出现个数。然后呢,对于1~n每个节点建一棵树,并且是基于前一棵树的基础上的。然后对于每一次的新值我们只需要update一次,并且连接一下原来的树?

神犇们不是说这种结构就是一堆线段树连啊连就出来了吗。

查询的时候呢?有一些小改变,据说是以二分为基础的查询。

神犇们发明这种数据结构的时候,就发现了这种数据结构里的所有线段树是可以相减的这种性质,于是,我们就可以二分答案在左边还是右边,递归搞下去最终的l就是目标值。

感觉要真正的理解还需要时间?我认为我现在就是理解个大概吧。

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 500010
using namespace std;
struct node
{
    int lson,rson,sum;
}seg[N*20];
int size;
int root[N];
void update(int p,int &q,int l,int r,int v)
{
    seg[++size]=seg[p],q=size;
    seg[q].sum++;
    if(l==r)return ;
    int mid=(l+r)>>1;
    if(v<=mid)update(seg[p].lson,seg[q].lson,l,mid,v);
    else update(seg[p].rson,seg[q].rson,mid+1,r,v);
}
int que(int L,int R,int l,int r,int k)
{
    if(l==r)return l;
    int mid=(l+r)>>1;
    if(seg[seg[R].lson].sum-seg[seg[L].lson].sum>k)
    {
        return que(seg[L].lson,seg[R].lson,l,mid,k);
    }
    if(seg[seg[R].rson].sum-seg[seg[L].rson].sum>k)
    {
        return que(seg[L].rson,seg[R].rson,mid+1,r,k);
    }
    return 0;
}
int n,m;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        update(root[i-1],root[i],1,n,x);
    }
    for(int i=1;i<=m;i++)
    {
        int L,R;
        scanf("%d%d",&L,&R);
        printf("%d\n",que(root[L-1],root[R],1,n,(R-L+1)>>1));
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-08 11:17:54

BZOJ 3524 [Poi2014]Couriers 可持久化线段树的相关文章

BZOJ 3524: [Poi2014]Couriers( 主席树 )

卡我空间.... 这道题应该是主席树入门题...无修改 , 离散化都不用...出题人业界良心啊 一开始的空白树我 build 出来结果就多了整整 2n 个 Node , 然后就 MLE 了... ( 双倍经验 , 另一道见上图 ) ---------------------------------------------------------------------------------------------- #include<cstdio> #include<cstring&g

BZOJ 3524: [Poi2014]Couriers

3524: [Poi2014]Couriers Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1905  Solved: 691[Submit][Status][Discuss] Description 给一个长度为n的序列a.1≤a[i]≤n.m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2.如果存在,输出这个数,否则输出0. Input 第一行两个数n,m.第二行n个数,a[i].接下来m行,

BZOJ 3123 SDOI2013 森林 可持久化线段树+倍增LCA+启发式合并

题目大意:给定一棵森林,每个点有权值,提供两种操作: 1.查询两点间路径上第k小的权值 2.将两个点之间连一条边 保证连接后仍是一座森林 可持久化线段树部分同Count On A Tree 只是这道题加了个连接操作 对于连接操作我们要用到启发式合并 就是把小的那棵树暴力重建 很简单的一个操作但是可以证明是均摊O(nlogn)的 大小我用了并查集 其实记录根就可以了 此外本题的多组数据是在逗比 记住testcase恒等于1就是了 NND我倍增LCA又写错了0.0 预处理时居然从大往小写的0.0 样

bzoj 2653 middle (可持久化线段树)

middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1981  Solved: 1097[Submit][Status][Discuss] Description 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个 长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数. 其中a<b<c<d.位置也从0开始标号

BZOJ 3524 [Poi2014]Couriers(二分+蒙特卡罗)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3524 [题目大意] 给一个长度为n的序列a.1≤a[i]≤n. m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2. 如果存在,输出这个数,否则输出0. [题解] 我们可以在[l,r]中随机一个位置检验这个位置上数是不是答案, 检测方法可以在数组中保存每个数在序列中的不同位置,二分即可 选中答案的概率为1/2,我们做k次蒙特卡罗,正确率

[BZOJ 3207] 花神的嘲讽计划Ⅰ【Hash + 可持久化线段树】

题目链接:BZOJ - 3207 题目分析 先使用Hash,把每个长度为 k 的序列转为一个整数,然后题目就转化为了询问某个区间内有没有整数 x . 这一步可以使用可持久化线段树来做,虽然感觉可以有更简单的做法,但是我没有什么想法... 代码 #include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #inclu

[BZOJ 3218] A + B Problem 【可持久化线段树 + 网络流】

题目连接:BZOJ - 3218 题目分析 题目要求将 n 个点染成黑色或白色,那么我们可以转化为一个最小割模型. 我们规定一个点 i 最后属于 S 集表示染成黑色,属于 T 集表示染成白色,那么对于每个点 i 就要连边 (S, i, B[i]) 和 (i, T, W[i]). 这样,如果一个点属于 S 集,就要割掉与 T 相连的边,就相当于失去了染成白色的收益. 我们再来考虑 “奇怪的点”,一个点 i 变成奇怪的点的条件是:i 是黑色且存在一个白色点 j 满足 j < i && L

【BZOJ 3674】可持久化并查集加强版&amp;【BZOJ 3673】可持久化并查集 by zky 用可持久化线段树破之

最后还是去掉异或顺手A了3673,,, 并查集其实就是fa数组,我们只需要维护这个fa数组,用可持久化线段树就行啦 1:判断是否属于同一集合,我加了路径压缩. 2:直接把跟的值指向root[k]的值破之. 3:输出判断即可. 难者不会,会者不难,1h前我还在膜这道题,现在吗hhh就当支持下zky学长出的题了. 3673: #include<cstdio> #include<cstring> #include<algorithm> #define read(x) x=ge

3524: [Poi2014]Couriers -- 主席树

3524: [Poi2014]Couriers Time Limit: 20 Sec  Memory Limit: 256 MB Description 给一个长度为n的序列a.1≤a[i]≤n.m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2.如果存在,输出这个数,否则输出0. Input 第一行两个数n,m.第二行n个数,a[i].接下来m行,每行两个数l,r,表示询问[l,r]这个区间. Output m行,每行对应一个答案. Sample