码迷,mamicode.com
首页 > 其他好文 > 详细

[静态主席树]Couriers

时间:2018-12-27 15:27:50      阅读:136      评论:0      收藏:0      [点我收藏+]

标签:upd   建立   持久   inline   持久化   区间   name   pre   col   

题目描述

给一个长度为n的序列a。1≤a[i]≤n。
m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。

 

输入

第一行两个数n,m(n,m≤500000)。
第二行n个数,a[i]。
接下来m行,每行两个数l,r,表示询问[l,r]这个区间。

 

输出

m行,每行对应一个答案。

 

样例输入

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

样例输出

1
0
3
0
4

思路:建立可持久化权值线段树
AC代码:
#include <iostream>
#include<cstdio>
using namespace std;

int x,n,m;
int ls[10000010],rs[10000010],num[10000010],tot=0;
int tree[500010];

inline void update(int pre,int& cur,int l,int r,int v){
    cur=++tot;
    num[cur]=num[pre]+1;
    if(l==r) return;
    ls[cur]=ls[pre],rs[cur]=rs[pre];
    int m=(l+r)>>1;
    if(v<=m) update(ls[pre],ls[cur],l,m,v);
    else update(rs[pre],rs[cur],m+1,r,v);
}

int ask(int ltree,int rtree,int k){
    int l=1,r=n;
    while(l<r){
        int m=(l+r)>>1;
        if(num[ls[rtree]]-num[ls[ltree]]>=k){
            ltree=ls[ltree],rtree=ls[rtree];
            r=m;
        }
        else if(num[rs[rtree]]-num[rs[ltree]]>=k){//区间内只可能有1个数出现次数超过一半
            ltree=rs[ltree],rtree=rs[rtree];
            l=m+1;
        }
        else return 0;
    }
    return l;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
      scanf("%d",&x);
      update(tree[i-1],tree[i],1,n,x);
    }
    while(m--){
        int l,r;scanf("%d%d",&l,&r);
        int ans=ask(tree[l-1],tree[r],(r-l+1)/2+1);
        printf("%d\n",ans);
    }
    return 0;
}

[静态主席树]Couriers

标签:upd   建立   持久   inline   持久化   区间   name   pre   col   

原文地址:https://www.cnblogs.com/lllxq/p/10184321.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!