[BZOJ 3489]A simple rmq problem
因为机房的网络管制实在是太厉(sang)害(bing)了
百度空间神马的根本不能上,就算上了也是慢的要死(你懂的)
于是,是时候体现博客园的强大了(作死)
祝我空降成功吧,喵~
这是我在 BZOJ 上 solve 的第 128 题, 不妨庆祝一下喵~
作为一个平时刷题看到什么做什么,懒得去挑题,又没有权限号来虐 bzoj 第 7 版的大傻叉来说,刷到 128 题还是真的很不容易……
正如那句真理: 题目做法和题目名字永远没有半毛钱关系
我们又很高兴的看到此题的做法果然——
和RMQ没有半毛钱关系
出题人在 noip 吧上曾说,std 是树套堆,又笑看大神一行树套 set 怒打出题人脸
可惜,像我这种傻 X ,既不会树套堆,又不会树套 set , 就只好请出傻 X 的专利 —— Straight Forward (又译 Brute Force)
令 next[i] 为 满足 j>i 且 a[i]==a[j] 的最小的 j (如果没有则为 N+1)
令 last[i] 为 满足 i<j 且 a[i]==a[j] 的最大的 i (如果没有则为 0)
则对于询问 [l..r] 明显我们要找的是 满足 l<=i<=r 且 0<=last[i]<l 且 r<next[i]<=N+1 的最大的 a[i]
额, 你问我怎么做?树套树套树就可以了, 然后……我写了个可持久化二维线段树
在 RE 和 MLE 中徘徊了许久后, 我居然跳过了 WA 和 TLE 直奔 AC 了!
而且只有 6816 MS O(∩_∩)O~ 果然我的线段树写法的常数还是很小的 有点小骄傲呢喵~
说指针慢的果然都是自己没写好喵~ @maoxiaohan1999
1 #include <cstdio> 2 #include <algorithm> 3 const int size=100025; 4 5 namespace IOspace 6 { 7 inline int getint() 8 { 9 register int num=0; 10 register char ch; 11 do ch=getchar(); while (ch<'0' || ch>'9'); 12 do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9'); 13 return num; 14 } 15 inline void putint(int num, char ch='\n') 16 { 17 char stack[15]; 18 register int top=0; 19 if (num==0) stack[top=1]='0'; 20 for ( ;num;num/=10) stack[++top]=num%10+'0'; 21 for ( ;top;top--) putchar(stack[top]); 22 if (ch) putchar(ch); 23 } 24 } 25 26 struct item {int val, last, next;}; 27 28 int N, M; 29 item a[size]; 30 int k[size]; 31 int last[size], next[size]; 32 inline int max(const int x, const int y) {return x>y?x:y;} 33 inline void swap(int & x, int & y) {int t=x; x=y; y=t;} 34 inline int cmp(int i, int j) {return a[i].last<a[j].last;} 35 36 struct nodey {int val; nodey * c[2];}; 37 struct nodex {nodey * val; nodex * c[2];}; 38 nodex MEMx[2000000], * PORTx=MEMx; 39 nodey MEMy[20000000], * PORTy=MEMy; 40 nodex * seg[size]; 41 inline nodex * newnodex(nodex * x) {nodex * t=PORTx++; if (x) *t=*x; return t;} 42 inline nodey * newnodey(nodey * y) {nodey * t=PORTy++; if (y) *t=*y; return t;} 43 void inserty(nodey *& p, int l, int r, int k, int v) 44 { 45 int m=(l+r)>>1; 46 p=newnodey(p); 47 p->val=max(p->val, v); 48 if (l==r) return ; 49 if (k<=m) inserty(p->c[0], l, m, k, v); 50 else inserty(p->c[1], m+1, r, k, v); 51 } 52 void insertx(nodex *& p, int l, int r, int x, int y, int v) 53 { 54 int m=(l+r)>>1; 55 p=newnodex(p); 56 inserty(p->val, 0, N+1, y, v); 57 if (l==r) return ; 58 if (x<=m) insertx(p->c[0], l, m, x, y, v); 59 else insertx(p->c[1], m+1, r, x, y, v); 60 } 61 int queryy(nodey * y, int l, int r, int y1, int y2) 62 { 63 int m=(l+r)>>1; 64 if (!y) return 0; 65 if (l==y1 && r==y2) return y->val; 66 if (y2<=m) return queryy(y->c[0], l, m, y1, y2); 67 else if (y1>m) return queryy(y->c[1], m+1, r, y1, y2); 68 return max(queryy(y->c[0], l, m, y1, m), queryy(y->c[1], m+1, r, m+1, y2)); 69 } 70 int queryx(nodex * x, int l, int r, int x1, int x2, int y1, int y2) 71 { 72 int m=(l+r)>>1; 73 if (!x) return 0; 74 if (l==x1 && r==x2) return queryy(x->val, 0, N+1, y1, y2); 75 if (x2<=m) return queryx(x->c[0], l, m, x1, x2, y1, y2); 76 else if (x1>m) return queryx(x->c[1], m+1, r, x1, x2, y1, y2); 77 return max(queryx(x->c[0], l, m ,x1, m, y1, y2), queryx(x->c[1], m+1, r, m+1, x2, y1, y2)); 78 } 79 80 int main() 81 { 82 N=IOspace::getint(), M=IOspace::getint(); 83 for (int i=1;i<=N;i++) last[i]=0, next[i]=N+1; 84 for (int i=1;i<=N;i++) 85 { 86 a[i].val=IOspace::getint(); 87 a[i].last=last[a[i].val]; 88 last[a[i].val]=i; 89 } 90 for (int i=N;i>=1;i--) 91 { 92 k[i]=i; 93 a[i].next=next[a[i].val]; 94 next[a[i].val]=i; 95 } 96 97 std::sort(k+1, k+N+1, cmp); 98 99 int j=1; 100 for (int i=0;i<N;i++) 101 { 102 if (i) seg[i]=seg[i-1]; 103 for ( ;a[k[j]].last==i && j<=N;j++) insertx(seg[i], 0, N+1, a[k[j]].next, k[j], a[k[j]].val); 104 } 105 106 int lastans=0; 107 for ( ;M;M--) 108 { 109 int l=IOspace::getint(), r=IOspace::getint(); 110 l=(l+lastans)%N+1, r=(r+lastans)%N+1; 111 if (l>r) swap(l, r); 112 lastans=queryx(seg[l-1], 0, N+1, r+1, N+1, l, r); 113 IOspace::putint(lastans); 114 } 115 116 return 0; 117 }