bzoj3489: A simple rmq problem
Posted f321dd
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3489: A simple rmq problem相关的知识,希望对你有一定的参考价值。
设$i$的前驱为$p_i$,后继为$q_i$,把询问看成点$(L,R)$,有贡献的$i$满足$L\in(p_i,i]$且$R\in[i,q_i)$,询问的就是覆盖这个点的矩形的最大值。那么可以用可持久化树套堆,插入矩形时一维可持久化,一维区间插入,用堆维护最大值。注意这里的“可持久化堆”只需要查询历史,因此只需要把最大值记下来就好了。
#include<algorithm> #include<cstdio> #include<queue> #define I (J+1) #define J (i+j>>1) #define P (k<<1) #define S (P^1) using namespace std; const int N=1e5+5; int n,m; typedef int arr[N]; arr p,q,f,a; struct heap{ priority_queue<int> s,t; void ins(int j){s.push(j);} void del(int j){t.push(j);} int top(){ while(t.size()&&s.top()==t.top()) s.pop(),t.pop(); return s.size()?s.top():0; } }c[1<<18]; typedef struct node* ptr; struct node{ ptr i,j;int s; }e[N*136]; ptr z=e+1,r[N]; int eval(int v,ptr s, int i=1,int j=n){ if(i==j)return s->s; return max(s->s,v<I ?eval(v,s->i,i,J) :eval(v,s->j,I,j)); } struct info{ void(heap::*foo)(int); int f,s,t; }; void vary(info f,ptr& s, int i=1,int j=n,int k=1){ s=&(*z++=*s); if(f.s<=i&&j<=f.t){ (c[k].*f.foo)(f.f); s->s=c[k].top(); }else{ if(f.s<I) vary(f,s->i,i,J,P); if(f.t>J) vary(f,s->j,I,j,S); } } struct edge{ edge* s;info f; }e2[N*2]; edge *z2=e2,*y[N]; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i){ scanf("%d",a+i); p[i]=f[a[i]],f[a[i]]=i; } fill(f+1,f+n+1,n+1); for(int i=n;i;--i) q[i]=f[a[i]],f[a[i]]=i; for(int i=n;i;--i){ int s=p[i]+1,t=i+1; edge u={y[s],&heap::ins,a[i],i,q[i]-1}; edge v={y[t],&heap::del,a[i],i,q[i]-1}; *(y[s]=z2++)=u; *(y[t]=z2++)=v; } *(*r=e)=(node){e,e}; for(int i=1;i<=n;++i){ r[i]=r[i-1]; for(edge* j=y[i];j;j=j->s) vary(j->f,r[i]); } int k=0,s,t; while(m--){ scanf("%d%d",&s,&t); if((s=(s+k)%n+1)>(t=(t+k)%n+1)) swap(s,t); printf("%d\n",k=eval(t,r[s])); } }
以上是关于bzoj3489: A simple rmq problem的主要内容,如果未能解决你的问题,请参考以下文章
[bzoj3489]A simple rmq problem
bzoj3489: A simple rmq problem