Couriers
阿新 • • 發佈:2019-02-13
courier sta uri href 一個數 turn lse getchar() name
提交: 91 解決: 21
[提交] [狀態] [討論版] [命題人:admin]
m組詢問,每次詢問一個區間[l,r],是否存在一個數在[l,r]中出現的次數大於(r-l+1)/2。如果存在,輸出這個數,否則輸出0。
第二行n個數,a[i]。
接下來m行,每行兩個數l,r,表示詢問[l,r]這個區間。
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) usingnamespace 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();} returnx; } 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