[POI2014]KUR-Couriers——[主席树]

【原题】
Byteasar works for the BAJ company, which sells computer games.

The BAJ company cooperates with many courier companies that deliver the games sold by the BAJ company to its customers.

Byteasar is inspecting the cooperation of the BAJ company with the couriers.

He has a log of successive packages with the courier company that made the delivery specified for each package.

He wants to make sure that no courier company had an unfair advantage over the others.

If a given courier company delivered more than half of all packages sent in some period of time, we say that it dominated in that period.

Byteasar wants to find out which courier companies dominated in certain periods of time, if any.

Help Byteasar out!

Write a program that determines a dominating courier company or that there was none.

【题目翻译】
给一个数列,每次询问一个区间内有没有一个数出现次数超过一半,并输出这个数

【输入格式】
第一行两个数n,m,表示有几个数,几个询问
接下来一行n个数,表示给定的数列
接下来m行每行两个数l,r,表示询问 [ l , r ] [l,r] [l,r]区间内有没有一个数出现次数超过一半

【输出格式】
m行,对于每个询问,如果没有出现次数超过一半的数,输出0,否则输出那个数。

S a m p l e    I n p u t Sample\;Input SampleInput

7 5
1 1 3 2 3 4 3
1 3
1 4
3 7
1 7
6 6

S a m p l e    O u t p u t Sample\;Output SampleOutput

1
0
3
0
4

【题意分析】
本来想写莫队的,得知n有500000后还是写了主席树

题解里面貌似好多人都没加上离散化QAQ

其实离散化也是可以加的,也跟正常操作没什么区别~

蒟蒻开始用的是这种离散化(主席树模板里的)

for (register int i = 1;i <= n;i++){
    scanf ("%d",&a[i].v);
    a[i].index = i;
}
sort (a+1,a+n+1,cmp); //按v排序
for (register int i = 1;i <= n;i++)
    rank[a[i].index] = i;

这玩意儿根本不叫离散化!!!!并不能去重,因此建议不要用这种。

正确的离散化(使用STL)

for (register int i = 1;i <= n;i++)
    scanf ("%d",&a[i]),b[i] = a[i]
sort (b+1,b+n+1);
p = unique (b+1,b+n+1)-b-1;

对于这道题,普通离散化+建树之后,对于读入的区间,取长度后进行询问,如果左子树大于mid的就继续往左走,右子树大于mid的就继续往右走,否则return 0。

Code:

#pragma GCC optimize(2)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cctype>
#include<cstring>
#include<vector>
#include<algorithm>
#define MAXN 500010
#define Read(a) a = SlowRead <int> ()
using namespace std;

struct Chairman_Tree{
    int size,l,r;
}tree[MAXN*40];

int size[MAXN],edit[MAXN],a[MAXN],b[MAXN],n,q,p,cnt;

//慢读
template <typename T> inline T SlowRead (){
    register int s = 0,w = 1;
    register char ch = getchar ();
    while (!isdigit (ch)){if (ch == '-')w = -1;ch = getchar ();}
    while (isdigit (ch)){s = (s << 3) + (s << 1) + ch - '0';ch = getchar ();}
    return s*w;
}

//建树
void build (int &now,int tl,int tr){
    now = ++cnt;
    if (tl == tr)return;
    int mid = (tl + tr) >> 1;
    build (tree[now].l,tl,mid);
    build (tree[now].r,mid+1,tr);
}

//加入
int update (int from,int tl,int tr,int change){
    int now = ++cnt;
    tree[now] = tree[from]; ++tree[now].size;
    if (tl == tr)return now;
    int mid = (tl + tr) >> 1;
    if (change <= mid)tree[now].l = update(tree[now].l,tl,mid,change);
    else tree[now].r = update (tree[now].r,mid+1,tr,change);
    return now;
}

//询问
int query (int left,int right,int tl,int tr,int length){
    if (tl == tr) return tl;
    int lvalue = tree[tree[right].l].size - tree[tree[left].l].size;
    int rvalue = tree[tree[right].r].size - tree[tree[left].r].size;
    int mid = (tl + tr) >> 1;
    if (lvalue > length)return query (tree[left].l,tree[right].l,tl,mid,length);
    else if (rvalue > length)return query (tree[left].r,tree[right].r,mid+1,tr,length);
    else return 0;
}

int main (){
    Read (n),Read(q);
    //离散化
    for (register int i = 1;i <= n;i++)
        Read (a[i]),b[i] = a[i];
    sort (b+1,b+n+1);
    p = unique (b+1,b+n+1)-b-1;
    build (edit[0],1,p);
    for (register int i = 1;i <= n;i++){
        int pos = lower_bound (b+1,b+p+1,a[i])-b;
        edit[i] = update (edit[i-1],1,p,pos);
    }
    while (q--){
        int l,r;
        Read(l),Read(r); int len = (r-l+1) >> 1;
        int ans = query (edit[l-1],edit[r],1,p,len);
        printf ("%d\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值