zoukankan      html  css  js  c++  java
  • 【BZOJ3489】A simple rmq problem(KD-Tree)

    (Description)

    因为是(OJ)上的题,就简单点好了。给出一个长度为(n)的序列,给出(M)个询问:在([l,r])之间找到一个在这个区间里只出现过一次的数,并且要求找的这个数尽可能大。如果找不到这样的数,则直接输出(0)。我会采取一些措施强制在线。


    (Input)

    第一行为两个整数(N,M)(M)是询问数,(N)是序列的长度((N<=100000,M<=200000))

    第二行为(N)个整数,描述这个序列{ai},其中所有(1<=a_{i}<=N)

    再下面(M)行,每行两个整数(x,y)

    询问区间([l,r])由下列规则产生((OIER)都知道是怎样的吧>_<):

    (l=min((x+lastans)\% n+1,(y+lastans)\% n+1);)

    (r=max((x+lastans)\% n+1,(y+lastans)\% n+1);)

    (Lastans)表示上一个询问的答案,一开始(lastans)(0)


    (Output)

    一共(M)行,每行给出每个询问的答案。


    (Sample) (Input)

    10 10
    6 4 9 10 9 10 9 4 10 4
    3 8
    10 1
    3 4
    9 4
    8 1
    7 8
    2 9
    1 1
    7 3
    9 9


    (Sample) (Output)

    4
    10
    10
    0
    0
    10
    0
    4
    0
    4


    (Source)

     练习题 树9-2-树套树
    

    思路

    对于这道题,我们首先考虑如何处理 (“)[l,r](区间内只出现一次”) 这个限制,我们两次循环处理出每个 (i) 位置 (a_{i}) 上次和下次出现的位置的 (pre)(nxt) ,也就是说,对于这个数(a_{i}),只出现一次的区间是([pre[a[i]],nxt[a[i]]])

    于是,我们将每个位置 (i) 看成一个点 ((i,pre[i],nxt[i])) ,这样,问题就转化为,求一个长方体中包含的点的最大值,这个问题我们用(KD-Tree)来解决

    当然,你在做题过程中很大几率会碰到(TLE)的情况,遇到这种情况,你可以考虑:

    1. 各种卡常奇技淫巧
    2. 将结构体套结构体换为一个结构体
    3. (KD-Tree)查询时进行优化

    详见丑陋的代码

    (p.s:) 代码写太丑排版挂掉了,建议 (ctrl+c)(ctrl+v) 到编译器上食用

    #include<bits/stdc++.h>
    using namespace std;
    const int N=100010;
    int n,m,nodetot=0,WD;
    int a[N];
    int pre[N],nxt[N];
    int st[N];
    struct point
    {
    	int x[3],val;
    	bool operator <(const point & b) const
    	{
    		if(x[WD]==b.x[WD])
    		{
    			if(x[(WD+1)%3]==b.x[(WD+1)%3])return x[(WD+2)%3]<b.x[(WD+2)%3];
    			return x[(WD+1)%3]<b.x[(WD+1)%3];
    		}
    		return x[WD]<b.x[WD];
    	} 
    }p[N];
    struct tree
    {
    	int siz,lc,rc,maxn,maxx[3],minn[3];
    	point pt;
    }t[N];
    inline void update(int k)
    {
    	t[k].siz=t[t[k].lc].siz+t[t[k].rc].siz+1;
    	t[k].maxn=max(t[k].pt.val,max(t[t[k].lc].maxn,t[t[k].rc].maxn));
    	for(int i=0;i<3;i++)
    	{
    		t[k].maxx[i]=t[k].minn[i]=t[k].pt.x[i];
    		if(t[k].lc)
    		{
    			t[k].maxx[i]=max(t[k].maxx[i],t[t[k].lc].maxx[i]);
    			t[k].minn[i]=min(t[k].minn[i],t[t[k].lc].minn[i]);
    		}
    		if(t[k].rc)
    		{
    			t[k].maxx[i]=max(t[k].maxx[i],t[t[k].rc].maxx[i]);
    			t[k].minn[i]=min(t[k].minn[i],t[t[k].rc].minn[i]);
    		}
    	}
    }
    int build(int l,int r,int wd)
    {
    	if(l>r)return 0;
    	int mid=(l+r)>>1,k=++nodetot;
    	WD=wd;
    	nth_element(p+l,p+mid,p+r+1);
    	t[k].pt=p[mid];
    	t[k].lc=build(l,mid-1,(wd+1)%3);
    	t[k].rc=build(mid+1,r,(wd+1)%3);
    	update(k);
    	return k;
    }
    
    inline bool in(int l1,int r1,int l2,int r2,int l3,int r3,int mn1,int mx1,int mn2,int mx2,int mn3,int mx3)
    {
    	return mn1>=l1&&mx1<=r1&&mn2>=l2&&mx2<=r2&&mn3>=l3&&mx3<=r3;
    }
    
    inline bool out(int l1,int r1,int l2,int r2,int l3,int r3,int mn1,int mx1,int mn2,int mx2,int mn3,int mx3)
    {
    	return mn1>r1||mx1<l1||mn2>r2||mx2<l2||mn3>r3||mx3<l3;
    }
    
    int query(int l1,int r1,int l2,int r2,int l3,int r3,int k)
    {
    	if(in(l1,r1,l2,r2,l3,r3,t[k].minn[0],t[k].maxx[0],t[k].minn[1],t[k].maxx[1],t[k].minn[2],t[k].maxx[2]))return t[k].maxn;	
    	int res=0;
    	if(in(l1,r1,l2,r2,l3,r3,t[k].pt.x[0],t[k].pt.x[0],t[k].pt.x[1],t[k].pt.x[1],t[k].pt.x[2],t[k].pt.x[2]))res=t[k].pt.val;
    	if(t[t[k].lc].maxn>t[t[k].rc].maxn)//就是这个优化
    	{
    		if(t[k].lc&&t[t[k].lc].maxn>res&&!out(l1,r1,l2,r2,l3,r3,t[t[k].lc].minn[0],t[t[k].lc].maxx[0],t[t[k].lc].minn[1],t[t[k].lc].maxx[1],t[t[k].lc].minn[2],t[t[k].lc].maxx[2]))res=max(res,query(l1,r1,l2,r2,l3,r3,t[k].lc));
    		if(t[k].rc&&t[t[k].rc].maxn>res&&!out(l1,r1,l2,r2,l3,r3,t[t[k].rc].minn[0],t[t[k].rc].maxx[0],t[t[k].rc].minn[1],t[t[k].rc].maxx[1],t[t[k].rc].minn[2],t[t[k].rc].maxx[2]))res=max(res,query(l1,r1,l2,r2,l3,r3,t[k].rc));
    	}
    	else 
    	{
    		if(t[k].rc&&t[t[k].rc].maxn>res&&!out(l1,r1,l2,r2,l3,r3,t[t[k].rc].minn[0],t[t[k].rc].maxx[0],t[t[k].rc].minn[1],t[t[k].rc].maxx[1],t[t[k].rc].minn[2],t[t[k].rc].maxx[2]))res=max(res,query(l1,r1,l2,r2,l3,r3,t[k].rc));
    		if(t[k].lc&&t[t[k].lc].maxn>res&&!out(l1,r1,l2,r2,l3,r3,t[t[k].lc].minn[0],t[t[k].lc].maxx[0],t[t[k].lc].minn[1],t[t[k].lc].maxx[1],t[t[k].lc].minn[2],t[t[k].lc].maxx[2]))res=max(res,query(l1,r1,l2,r2,l3,r3,t[k].lc));
    	}
    	return res;
    }
    
    inline int read()
    {
    	int x=0;
    	char ch=getchar();
    	while(!isdigit(ch))ch=getchar();
    	while(isdigit(ch))
    	{
    		x=(x<<3)+(x<<1)+(ch^48);
    		ch=getchar();
    	}
    	return x;
    }
    
    int main()
    {
    	n=read(),m=read();
    	for(register int i=1;i<=n;i++)a[i]=read();
    	for(register int i=1;i<=n;i++)
    		pre[i]=st[a[i]],st[a[i]]=i;
    	for(register int i=1;i<=n;i++)st[a[i]]=n+1;
    	for(register int i=n;i>=1;i--)
    		nxt[i]=st[a[i]],st[a[i]]=i;
    	for(register int i=1;i<=n;i++)
    		p[i].x[0]=i,p[i].x[1]=pre[i],p[i].x[2]=nxt[i],p[i].val=a[i];
    	build(1,n,0);
    	int lastans=0;
    	int x,y,l,r;
    	for(register int i=1;i<=m;i++)
    	{
    		x=read(),y=read();
    		x=(x+lastans)%n,y=(y+lastans)%n;x++,y++;
    		l=min(x,y),r=max(x,y);
    		printf("%d
    ",lastans=query(l,r,0,l-1,r+1,n+1,1));
    	}
    	return 0;
    }
    
  • 相关阅读:
    Iphone开发-NSdata 与 NSString,Byte数组,UIImage 的相互转换
    Iphone访问WCF服务 之 ASIHTTPRequest
    TP6 实现上传文件
    页面自适应纯CSS,使用rem单位
    jQuery解决高度统一问题
    dedecms Ajax异步获取文章列表
    手机端页面自适应解决方案—rem布局
    mysql中bigint、int、mediumint、smallint 和 tinyint的取值范围
    修改PHP 上传文件大小限制
    WampServer下修改和重置MySQL密码
  • 原文地址:https://www.cnblogs.com/ShuraEye/p/12198457.html
Copyright © 2011-2022 走看看