给一个长度为n的序列a。1≤a[i]≤n。
m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。
标签:
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3524
给一个长度为n的序列a。1≤a[i]≤n。
m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。
第一行两个数n,m。
第二行n个数,a[i]。
接下来m行,每行两个数l,r,表示询问[l,r]这个区间。
m行,每行对应一个答案。
主席树 OrzTLE Orz林教主
注意数组大小,这题卡空间……
做了一下询问过程加inline,不加inline和直接塞进主函数的效率对比
从上到下依次是直接塞进主函数,加inline,不加inline
加与不加之间相差大约300ms,直接塞进主函数和加inline运行时间没有太大区别
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #define rep(i,l,r) for(int i=l; i<=r; i++) 6 #define clr(x,y) memset(x,y,sizeof(x)) 7 #define travel(x) for(Edge *p=last[x]; p; p=p->pre) 8 using namespace std; 9 const int INF = 0x3f3f3f3f; 10 const int maxn = 500010; 11 int n,m,x,y,tot=0,a[maxn],root[maxn],ls[maxn*20],rs[maxn*20],sum[maxn*20]; 12 inline int read(){ 13 int ans = 0, f = 1; 14 char c = getchar(); 15 while (!isdigit(c)){ 16 if (c == ‘-‘) f = -1; 17 c = getchar(); 18 } 19 while (isdigit(c)){ 20 ans = ans * 10 + c - ‘0‘; 21 c = getchar(); 22 } 23 return ans * f; 24 } 25 void insert(int l,int r,int x,int &y,int v){ 26 y = ++tot; 27 sum[y] = sum[x] + 1; 28 if (l == r) return; 29 ls[y] = ls[x]; rs[y] = rs[x]; 30 int mid = (l + r) >> 1; 31 if (v <= mid) insert(l,mid,ls[x],ls[y],v); 32 else insert(mid+1,r,rs[x],rs[y],v); 33 } 34 inline void query(int x,int y){ 35 int l=1,r=n,a=root[y],b=root[x-1]; 36 while (l < r){ 37 int mid = (l + r) >> 1; 38 if (sum[ls[a]] - sum[ls[b]] > sum[rs[a]] - sum[rs[b]]){ 39 a = ls[a]; b = ls[b]; r = mid; 40 } 41 else{ 42 a = rs[a]; b = rs[b]; l = mid + 1; 43 } 44 } 45 if (sum[a] - sum[b] > (y - x + 1) >> 1) printf("%d\n",l); 46 else printf("0\n"); 47 } 48 int main(){ 49 n = read(); m = read(); 50 rep(i,1,n) a[i] = read(); 51 rep(i,1,n) insert(1,n,root[i-1],root[i],a[i]); 52 rep(i,1,m){ 53 x = read(); y = read(); 54 query(x,y); 55 } 56 return 0; 57 }
标签:
原文地址:http://www.cnblogs.com/jimzeng/p/bzoj3524.html