BZOJ 3524 POI 2014 Couriers 主席树

题目大意

给出一个序列,问一段区间内有没有出现过一半以上的数字。

思路

用主席树取区间出来,在权值线段树上找。

CODE

#define _CRT_SECURE_NO_WARNINGS

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 500010
#define MAXR 10000010
using namespace std;

struct SegTree{
    SegTree *son[2];
    int cnt;
}mempool[MAXR], *C = mempool, *root[MAX];

SegTree *NewSegTree(SegTree *_, SegTree *__, int ___)
{
    C->son[0] = _;
    C->son[1] = __;
    C->cnt = ___;
    return C++;
}

SegTree *Insert(SegTree *consult, int l, int r, int x)
{
    if(l == r)
        return NewSegTree(consult->son[0], consult->son[1], consult->cnt + 1);
    int mid = (l + r) >> 1;
    if(x <= mid)
        return NewSegTree(Insert(consult->son[0], l, mid, x), consult->son[1], consult->cnt + 1);
    else
        return NewSegTree(consult->son[0], Insert(consult->son[1], mid + 1, r, x), consult->cnt + 1);
}

int Ask(SegTree *left, SegTree *right, int l, int r, int c)
{
    if(l == r)  return l;
    int mid = (l + r) >> 1;
    if(right->son[0]->cnt - left->son[0]->cnt > c)
        return Ask(left->son[0], right->son[0], l, mid, c);
    else if(right->son[1]->cnt - left->son[1]->cnt > c)
        return Ask(left->son[1], right->son[1], mid + 1, r, c);
    return 0;
}

int cnt, asks;

int main()
{
    root[0] = NewSegTree(C, C, 0);
    cin >> cnt >> asks;
    for(int x, i = 1; i <= cnt; ++i) {
        scanf("%d", &x);
        root[i] = Insert(root[i - 1], 1, cnt, x);
    }
    for(int x, y, i = 1; i <= asks; ++i) {
        scanf("%d%d", &x, &y);
        printf("%d\n", Ask(root[x - 1], root[y], 1, cnt, (y - x + 1) / 2));
    }
    return 0;
}
时间: 2024-10-02 23:12:45

BZOJ 3524 POI 2014 Couriers 主席树的相关文章

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

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

[BZOJ2223][BZOJ3524][Poi2014]Couriers 主席树

3524: [Poi2014]Couriers Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 2436  Solved: 960[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 4571][Scoi2016]美味(主席树)

Description 一家餐厅有 n 道菜,编号 1...n ,大家对第 i 道菜的评价值为 ai(1≤i≤n).有 m 位顾客,第 i 位顾客的期 望值为 bi,而他的偏好值为 xi .因此,第 i 位顾客认为第 j 道菜的美味度为 bi XOR (aj+xi),XOR 表示异或 运算.第 i 位顾客希望从这些菜中挑出他认为最美味的菜,即美味值最大的菜,但由于价格等因素,他只能从第 li 道到第 ri 道中选择.请你帮助他们找出最美味的菜. Solution 按位贪心,每次通过查询一段区间是

【BZOJ 3772】精神污染 主席树+欧拉序

这道题的内存-------真·精神污染---.. 这道题的思路很明了,我们就是要找每一个路径包含了多少其他路径那么就是找,有多少路径的左右端点都在这条路径上,对于每一条路径,我们随便选定一个端点作为第一关键字,另一个作为第二关键字,于是就有了两维限制,按照主席树的一般思路,我们把建树顺序作为一维,然后在里面维护另一维,那么我们在外面限制第一关键字,就是在树上建主席树,查询减LCA,在里面的话我们把每个点作为第一关键字对应的第二关键字,放入主席树,而主席树维护的是欧拉序区间,所以我们每次查询只用查

【BZOJ 3123】 [Sdoi2013]森林 主席树启发式合并

我们直接按父子关系建主席树,然后记录倍增方便以后求LCA,同时用并查集维护根节点,而且还要记录根节点对应的size,用来对其启发式合并,然后每当我们合并的时候我们都要暴力拆小的一部分重复以上部分,总时间复杂度为O(n*log),因为每个的节点只会作为小的部分合并,因此他所在的一小部分至少变大2倍,对于每一个节点他作为被合并方最多log次,因此其复杂度为O(n*log),而这个是绝对跑不满还差很多的,我们视他为无常数就好了,当然这一切都是建立在无拆分操作的基础之上,只要有了拆分启发式合并的复杂度就

BZOJ 1878 HH的项链(主席树)

对于该题,离线的做法是树状数组或者线段树. 如果强制在线的话,可以用主席树做到O(mlogn). 考虑到这样一个性质,对于询问[l,r]出现的数字种数.其答案就是to[i]>r的数字数. 其中to[i]表示的是第i个数的下一个相同的数出现的下标,没有则=n+1. 很幸运这个性质是满足区间减法的,也就是说对于[1,r]和[1,l-1]的to[i]域,是可以相减得到[l,r]的to[i]域的. 于是我们可以用主席树来解决这个问题. 对于一组询问,实际上就是求[l-1,r]这颗线段树上的区间[r+1,

BZOJ 2006 超级钢琴(堆+主席树)

很好的一道题. 题意:给出长度为n的数列,选择k个互不相同的区间,满足每个区间长度在[L,R]内,求所有选择的区间和的总和最大是多少.(n,k<=5e5). 首先将区间和转化为前缀和之差,那么我们想要区间和的总和最大,一个朴素的想法是把所有满足限制的区间和排序,取最大的k个. 考虑每个右端点i,其中有效的左端点是[i-R+1,i-L+1].如果我们对于每个右端点都找到"当前"最大的区间和,那么把它们扔进大根堆里维护一下即可. 由于sum[i]一定,那么只要左端点的sum值越小越好

bzoj 1901: Zju2112 Dynamic Rankings -- 主席树,树状数组,哈希

1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MB Description 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1 ],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改 变后的a继续回答上面的问题. Input 第一行有两个正整数n(1≤

bzoj 3545/3551: [ONTAK2010]Peaks -- 主席树,最小生成树,倍增

3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MB Description 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1. Input 第一行三个数N,M,Q.第二行N个数,第i个数为h_i接下来M行,每行