BZOJ5178: [Jsoi2011]棒棒糖

BZOJ

题意

给你\(n\)个数,每次询问一个区间\([l,r]\)是否存在一个出现次数严格大于\(\frac{r-l+1}{2}\)的数,如果有,输出这个数,否则输出0;

题解

主席树上二分,到了叶子节点再判一下出现次数;

#include<bits/stdc++.h>
#define Fst first
#define Snd second
#define RG register
#define mp make_pair
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long LL;
typedef long double LD;
typedef unsigned int UI;
typedef unsigned long long ULL;
template<typename T> inline void read(T& x) {
    char c = getchar();
    bool f = false;
    for (x = 0; !isdigit(c); c = getchar()) {
        if (c == '-') {
            f = true;
        }
    }
    for (; isdigit(c); c = getchar()) {
        x = x * 10 + c - '0';
    }
    if (f) {
        x = -x;
    }
}
template<typename T, typename... U> inline void read(T& x, U& ... y) {
    read(x), read(y...);
}
const int MAX=5e4,N=MAX+10;
int n,Q,size;
int root[N];
struct Node {
    int lo,ro,sum;
}Tr[N*20];
void Modify(int l,int r,int &o,int pos) {
    Tr[++size]=Tr[o]; o=size;
    ++Tr[o].sum;
    if(l==r) return;
    int mid=l+r>>1;
    if(pos<=mid) Modify(l,mid,Tr[o].lo,pos);
    else Modify(mid+1,r,Tr[o].ro,pos);
}
int Query(int l,int r,int x,int y,int len,int g) {
    if(l==r) return Tr[x].sum-Tr[y].sum>len?l:0;
    int mid=l+r>>1,t=Tr[Tr[x].lo].sum-Tr[Tr[y].lo].sum;
    if(t+g>len) return Query(l,mid,Tr[x].lo,Tr[y].lo,len,g);
    return Query(mid+1,r,Tr[x].ro,Tr[y].ro,len,g+t);
}
int main() {
//  ios::sync_with_stdio(false);
#ifdef rua
    freopen("GG.in","r",stdin);
#endif
    read(n,Q);
    for(int i=1;i<=n;++i) {
        int a; read(a);
        Modify(1,MAX,root[i]=root[i-1],a);
    }
    while(Q--) {
        int l,r; read(l,r);
        printf("%d\n",Query(1,MAX,root[r],root[l-1],(r-l+1)/2,0));
    }
    return 0;
}

转载于:https://www.cnblogs.com/ak12/p/10221151.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值