1. 程式人生 > >Couriers

Couriers

courier sta uri href 一個數 turn lse getchar() name

10324: Couriers

時間限制: 1 Sec 內存限制: 256 MB
提交: 91 解決: 21
[提交] [狀態] [討論版] [命題人:admin]

題目描述

給一個長度為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
思路:主席樹記錄每個節點儲存的個數,判斷左右節點是否符合條件,遞歸到葉節點。
#include<bits/stdc++.h>
#include<queue>
#include<cstdio>
#include<iostream>
#define REP(i, a, b) for(int i = (a); i <= (b); ++ i)
#define REP(j, a, b) for(int j = (a); j <= (b); ++ j)
#define PER(i, a, b) for(int i = (a); i >= (b); -- i)
using
namespace std; const int maxn=5e5+10; int p[maxn],t[maxn],rt[maxn],lr[10000010],rr[10000010],cnt,tot,c[10000010],n,m; inline int read() { char ch=getchar(); while(!(ch>=0&&ch<=9))ch=getchar(); int x=0; while(ch>=0&&ch<=9){x=x*10+(ch-0);ch=getchar();} return
x; } void update(int l,int r,int x,int &y,int val){ y=++tot,c[y]=c[x]+1; if(l==r)return; lr[y]=lr[x],rr[y]=rr[x]; int mid=(l+r)>>1; if(val<=mid)update(l,mid,lr[x],lr[y],val); else update(mid+1,r,rr[x],rr[y],val); } int query(int l,int r,int x,int &y,int val){ if(l==r)return l; int mid=l+r>>1; if(c[lr[y]]-c[lr[x]]>=val)return query(l,mid,lr[x],lr[y],val); else if(c[rr[y]]-c[rr[x]]>=val)return query(mid+1,r,rr[x],rr[y],val); return 0; } int main() { scanf("%d%d",&n,&m); REP(i, 1, n){ scanf("%d",&p[i]); t[i]=p[i]; } sort(t+1,t+1+n); cnt=unique(t+1,t+1+n)-t-1; REP(i, 1, n){ int cur=lower_bound(t+1,t+1+cnt,p[i])-t; update(1,cnt,rt[i-1],rt[i],cur); } REP(i, 1, m){ int l,r; scanf("%d%d",&l,&r); int ac=query(1,cnt,rt[l-1],rt[r],(r-l+1)/2+1); if(!ac)puts("0"); else printf("%d\n",t[ac]); } }

 

Couriers