[主席树套堆 区间修改 标记永久化] BZOJ 3489 A simple rmq problem

“因为是OJ上的题,就简单点好了。” Orz

看看贴吧吧:http://tieba.baidu.com/p/2947256742#47989538012l


题目大意:区间只出现过一次的最大的数


记一下next 

从左到右 删了之前的标记 再从这个点到next-1都打标记 然后就可以查询了

按一个坐标离线做强制转在线么 用主席树好了 第一次打主席树区间修改 空间两个log 不过这个的前提是标记永久化 不然就是n2了

 

#include
#include
#include
#include
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 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;
}


你可能感兴趣的:(堆,树套树,主席树,可持久化数据结构)