[主席樹套堆 區間修改 標記永久化] BZOJ 3489 A simple rmq problem
阿新 • • 發佈:2019-02-17
“因為是OJ上的題,就簡單點好了。” Orz
題目大意:區間只出現過一次的最大的數
記一下next
從左到右 刪了之前的標記 再從這個點到next-1都打標記 然後就可以查詢了
按一個座標離線做強制轉線上麼 用主席樹好了 第一次打主席樹區間修改 空間兩個log 不過這個的前提是標記永久化 不然就是n2了
#include<cstdio> #include<cstdlib> #include<algorithm> #include<queue> using namespace std; typedef long long ll; inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x) { char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int N=100005; struct Heap{ priority_queue<int> q,del; void maintain() { while (!del.empty() && !q.empty() && del.top()==q.top()) del.pop(),q.pop(); } bool empty() { return q.size()==del.size(); } int top() { if (empty()) return 0; maintain(); return q.top(); } void push(int x) { maintain(); q.push(x); } void erase(int x) { maintain(); del.push(x); } }; int ncnt,rcnt; int root[N*120],ls[N*120],rs[N*120],maxv[N*120]; Heap T[N*4]; inline void add(int &y,int x,int pos,int l,int r,int L,int R,int v){ y=++ncnt; int mid=(l+r)>>1; if (L<=l && r<=R) { T[pos].push(v); maxv[y]=T[pos].top(); ls[y]=ls[x]; rs[y]=rs[x]; return; } maxv[y]=maxv[x]; if (R<=mid) add(ls[y],ls[x],pos<<1,l,mid,L,R,v),rs[y]=rs[x]; else if (L>mid) add(rs[y],rs[x],pos<<1|1,mid+1,r,L,R,v),ls[y]=ls[x]; else add(ls[y],ls[x],pos<<1,l,mid,L,mid,v),add(rs[y],rs[x],pos<<1|1,mid+1,r,mid+1,R,v); } inline void del(int &y,int x,int pos,int l,int r,int L,int R,int v){ y=++ncnt; int mid=(l+r)>>1; if (L<=l && r<=R) { T[pos].erase(v); maxv[y]=T[pos].top(); ls[y]=ls[x]; rs[y]=rs[x]; return; } maxv[y]=maxv[x]; if (R<=mid) del(ls[y],ls[x],pos<<1,l,mid,L,R,v),rs[y]=rs[x]; else if (L>mid) del(rs[y],rs[x],pos<<1|1,mid+1,r,L,R,v),ls[y]=ls[x]; else del(ls[y],ls[x],pos<<1,l,mid,L,mid,v),del(rs[y],rs[x],pos<<1|1,mid+1,r,mid+1,R,v); } inline int query(int x,int t,int l,int r){ if (l==r) return maxv[x]; int mid=(l+r)>>1; if (t<=mid) return max(maxv[x],query(ls[x],t,l,mid)); else return max(maxv[x],query(rs[x],t,mid+1,r)); } int n,a[N]; int nxt[N],last[N]; int ed[N]; int main() { int l,r,lastans,Q; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); read(Q); for (int i=1;i<=n;i++) read(a[i]); for (int i=1;i<=n;i++) last[i]=n+1; for (int i=n;i;i--) nxt[i]=last[a[i]],last[a[i]]=i; for (int i=1;i<=n;i++) if (last[i]!=n+1) rcnt++,add(root[rcnt],root[rcnt-1],1,1,n,last[i],nxt[last[i]]-1,i); ed[1]=root[rcnt]; for (int i=1;i<=n;i++) { rcnt++,del(root[rcnt],root[rcnt-1],1,1,n,i,nxt[i]-1,a[i]); if (nxt[i]!=n+1) rcnt++,add(root[rcnt],root[rcnt-1],1,1,n,nxt[i],nxt[nxt[i]]-1,a[i]); ed[i+1]=root[rcnt]; } lastans=0; while (Q--) { read(l); read(r); l=(l+lastans)%n+1; r=(r+lastans)%n+1; if (l>r) swap(l,r); lastans=query(ed[l],r,1,n); printf("%d\n",lastans); } return 0; }