zoukankan      html  css  js  c++  java
  • BZOJ 3489 A simple rmq problem(可持久化线段树)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3489

    题意:一个数列。每次询问一个区间内出现一次的最大的数字是多少。

    思路:设last[i]表示i位置的数字上一次出现的位置,next[i]类似。那么询问区间[L,R]时,这个区间的哪些数字可以只出现一次呢?是那些last值小于L且next值大于R的数字。因此按照last排序后,按照last可持久化。具体看代码吧 不好说

    const int N=100005;
    
    struct node
    {
    	int val,last,next,id;
    };
    
    node b[N];
    int last[N],next[N],n,m;
    
    struct Node1
    {
    	int Max;
    	int L,R;
    };
    
    struct Node2
    {
    	int root;
    	int L,R;
    };
    
    
    Node1 A[40000005];
    Node2 a[N*20];
    int ANum,aNum;
    
    int cmp(node a,node b)
    {
    	return a.last<b.last;
    }
    
    int root[N];
    
    void insert1(int &t,int L,int R,int pos,int val)
    {
    	int cur=++ANum;
    	A[cur]=A[t];
    	t=cur;
    	A[t].Max=max(A[t].Max,val);
    
    	if(L==R) return;
    
    	int M=(L+R)>>1;
    	if(pos<=M) insert1(A[t].L,L,M,pos,val);
    	else insert1(A[t].R,M+1,R,pos,val);
    }
    
    void insert(int &t,int L,int R,int posX,int posY,int val)
    {
    	int cur=++aNum;
    	a[cur]=a[t];
    	t=cur;
    	insert1(a[t].root,1,n,posY,val);
    	if(L==R) return;
    	int M=(L+R)>>1;
    	if(posX<=M) insert(a[t].L,L,M,posX,posY,val);
    	else insert(a[t].R,M+1,R,posX,posY,val);
    }
    
    
    
    
    
    int query1(int t,int L,int R,int ll,int rr)
    {
    	if(!t) return 0;
    	if(L==ll&&R==rr) return A[t].Max;
    	int M=(L+R)>>1;
    	if(rr<=M) return query1(A[t].L,L,M,ll,rr);
    	if(ll>M) return query1(A[t].R,M+1,R,ll,rr);
    	int ans1=query1(A[t].L,L,M,ll,M);
    	int ans2=query1(A[t].R,M+1,R,M+1,rr);
    	return max(ans1,ans2);
    }
    
    int query(int t,int L,int R,int ll,int rr,int ll1,int rr1)
    {
    	if(L==ll&&R==rr) return query1(a[t].root,1,n,ll1,rr1);
    	int M=(L+R)>>1;
    	if(rr<=M) return query(a[t].L,L,M,ll,rr,ll1,rr1);
    	if(ll>M) return query(a[t].R,M+1,R,ll,rr,ll1,rr1);
    	int ans1=query(a[t].L,L,M,ll,M,ll1,rr1);
    	int ans2=query(a[t].R,M+1,R,M+1,rr,ll1,rr1);
    	return max(ans1,ans2);
    }
    
    int main()
    {
    	//FFF;
    
    	n=getInt(); m=getInt();
    	int i;
    	for(i=1;i<=n;i++) b[i].val=getInt(),b[i].id=i,last[i]=0,next[i]=n+1;
    	for(i=1;i<=n;i++)
    	{
    		b[i].last=last[b[i].val];
    		last[b[i].val]=i;
    	}
    	for(i=n;i>=1;i--)
    	{
    		b[i].next=next[b[i].val];
    		next[b[i].val]=i;
    	}
    	sort(b+1,b+n+1,cmp);
    	int j=1;
    	for(i=0;i<n;i++)
    	{
    		if(i) root[i]=root[i-1];
    		while(j<=n&&b[j].last==i)
    		{
    			insert(root[i],0,n+1,b[j].next,b[j].id,b[j].val);
    			j++;
    		}
    	}
    
    	int ans=0;
    	while(m--)
    	{
    		int L=getInt();
    		int R=getInt();
    		L=(L+ans)%n+1;
    		R=(R+ans)%n+1;
    		if(L>R) swap(L,R);
    		ans=query(root[L-1],0,n+1,R+1,n+1,L,R);
    		printf("%d
    ",ans);
    	}
    }
    
  • 相关阅读:
    Android随笔使用ViewPager实现简单地图片的左右滑动切换
    简单地Android中图片的三级缓存机制
    Java中怎么遍历map中value值 (转载)
    创建可执行的jar包
    写出优秀的java代码(转载)
    [JS脚本]ajax status 错误定义
    jsonlib 之jsonConfig详细使用(转载写的不错)
    Driver not found Error when sonar server is just not running
    使用Maven生成manifest
    ECMAScript 面向对象技术
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/4063608.html
Copyright © 2011-2022 走看看