zoukankan      html  css  js  c++  java
  • 【bzoj3489】A simple rmq problem

    Portal -->bzoj3489

    Solution

      最近计划智力康复qwq(话说这题一年前刚刚开始写树套树的时候感觉好难啊qwq现在看其实还好也算是有进步的嘛!)

      比较重要的一步是,要将“在([l,r])中只出现一次”这个条件转化成"(nxt[x]>r)&&(pre[x]<l)",其中(nxt[x])表示下一个出现位置(x)的数的位置,(pre[x])表示前一个

      然后我们就发现其实是有三个限制:

    1、(pre[x]<l)

    2、(nxt[x]>r)

    3、最大

      那所以我们用两棵主席树套在一起就好了

    ​  外层的主席树按照(pre[x])来顺序加点,树内按照(nxt)的顺序为关键字,然后对于每个节点(也就是区间啦),再开一棵主席树,以(nxt)为根的顺序,树内以(val[x])为关键字(也就是权值线段树啦)

    ​  然后修改直接修改,查询的时候我们先二分一下外层主席树应该调用哪个(rt),也就是二分一个最大的(pos)满足(pre[pos]<l),然后(query(rt[pos],l,r))即可

      想清楚了的话还是比较好写的

      有一些需要稍微注意一下的小细节

    1、如果说对于那些后面已经没有与其相同的数的位置,为了方便我们将其(nxt)赋成(n+1),所以这里要注意主席树的区间应该是([1,n+1])

    2、查询的时候,要注意因为我们要求的是(nxt[x]>r),所以在查询中涉及到的范围应该是(>)而不是(>=)之类的,跟平时写线段树有那么一点点小区别稍微注意一下

      

      代码大概长这个样子

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=100010,M=200010,SEG=N*20;
    struct Data{
    	int pre,nxt,id,val;
    	friend bool operator < (Data x,Data y)
    	{return x.pre<y.pre;}
    }a[N];
    int loc[N];
    int n,m,ans;
    namespace NodeSeg{/*{{{*/
    	int ch[SEG*20][2],mx[SEG*20],rt[SEG];
    	int n,tot;
    	int newnode(int pre){
    		ch[++tot][0]=ch[pre][0],ch[tot][1]=ch[pre][1]; mx[tot]=mx[pre];
    		return tot;
    	}
    	void pushup(int x){mx[x]=max(mx[ch[x][0]],mx[ch[x][1]]);}
    	void _update(int pre,int &x,int lx,int rx,Data &delta){
    		x=newnode(pre);
    		if (lx==rx){mx[x]=delta.val;return;}
    		int mid=lx+rx>>1;
    		if (delta.id<=mid) _update(ch[pre][0],ch[x][0],lx,mid,delta);
    		else _update(ch[pre][1],ch[x][1],mid+1,rx,delta);
    		pushup(x);
    	}
    	void update(int pre,int x,Data delta){_update(rt[pre],rt[x],1,n,delta);}
    	int _query(int x,int l,int r,int lx,int rx){
    		if (mx[x]==0) return 0;
    		if (l<=lx&&rx<=r) return mx[x];
    		int mid=lx+rx>>1,ret=0;
    		if (l<=mid) ret=max(ret,_query(ch[x][0],l,r,lx,mid));
    		if (r>mid) ret=max(ret,_query(ch[x][1],l,r,mid+1,rx));
    		return ret;
    	}
    	int query(int x,int l,int r){return _query(rt[x],l,r,1,n);}
    }/*}}}*/
    namespace NextSeg{/*{{{*/
    	int ch[SEG][2],rt[SEG];
    	int n,tot;
    	int newnode(int pre,Data delta){
    		ch[++tot][0]=ch[pre][0]; ch[tot][1]=ch[pre][1];
    		NodeSeg::update(pre,tot,delta);
    		return tot;
    	}
    	void _update(int pre,int &x,int lx,int rx,Data delta){
    		x=newnode(pre,delta);
    		if (lx==rx) return;
    		int mid=lx+rx>>1;
    		if (delta.nxt<=mid) _update(ch[pre][0],ch[x][0],lx,mid,delta);
    		else _update(ch[pre][1],ch[x][1],mid+1,rx,delta);
    	}
    	void update(int x,Data delta){_update(rt[x-1],rt[x],1,n,delta);}
    	int _query(int x,int l,int r,int lx,int rx){
    		if (r<lx&&rx<=n) return NodeSeg::query(x,l,r);
    		int mid=lx+rx>>1,ret=0;
    		if (r<mid) ret=max(ret,_query(ch[x][0],l,r,lx,mid));
    		ret=max(ret,_query(ch[x][1],l,r,mid+1,rx));
    		return ret;
    	}
    	int query(int x,int l,int r){return _query(rt[x],l,r,1,n);}
    }/*}}}*/
    int read(){
    	int ret=0; char ch=getchar();
    	while (ch<'0'||ch>'9') ch=getchar();
    	while ('0'<=ch&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
    	return ret;
    }
    
    void prework(){
    	for (int i=1;i<=n;++i) a[i].pre=0,a[i].nxt=n+1;
    	for (int i=1;i<=n;++i){
    		a[i].id=i;
    		if (loc[a[i].val]) 
    			a[loc[a[i].val]].nxt=i,a[i].pre=loc[a[i].val];
    		loc[a[i].val]=i;
    	}
    	NodeSeg::n=n+1; NextSeg::n=n+1;
    }
    
    int get_pos(int x){
    	int l=1,r=n,mid,ret=l;
    	while (l<=r){
    		mid=l+r>>1;
    		if (x<=a[mid].pre) r=mid-1;
    		else l=mid+1;
    	}
    	return l-1;
    }
    
    int main(){/*{{{*/
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    #endif
    	int x,y,x1,y1,pos;
    	n=read(); m=read();
    	for (int i=1;i<=n;++i) a[i].val=read();
    	prework();
    	sort(a+1,a+1+n);
    	for (int i=1;i<=n;++i)
    		NextSeg::update(i,a[i]);
    	for (int i=1;i<=m;++i){
    		x1=read(); y1=read();
    		x=min((x1+ans)%n+1,(y1+ans)%n+1);
    		y=max((x1+ans)%n+1,(y1+ans)%n+1);
    		pos=get_pos(x);
    		ans=NextSeg::query(pos,x,y);
    		printf("%d
    ",ans);
    	}
    }/*}}}*/
    
  • 相关阅读:
    IIS配置跨域请求
    ABP框架页面权限验证
    WPF-DataGrid增删改查不绑定数据源
    WPF-DataGrid增删改查绑定数据源
    .NET开发框架集合(长期更新)
    C# Webbrowser 常用方法及多线程调用
    Devexpress-GridLookUpEdit
    Devexpress提示框的使用
    Asp.Net MVC中Action跳转小结
    ASP.NET MVC备忘
  • 原文地址:https://www.cnblogs.com/yoyoball/p/9313850.html
Copyright © 2011-2022 走看看