zoukankan      html  css  js  c++  java
  • 「CF522D Closest Equals」

    题目大意

    给出一个序列,每次查询一段区间内距离最近的相同元素之间的距离.

    分析

    RMQ+二分的做法好妙啊,我就根本想不出来.

    考虑一个数对只有当两个数相等且都在区间内才可能会产生贡献.

    记录一个 (pre_i) 表示第 (i) 个数相同的数上一次出现的位置

    这个东西就很像区间取 (min) 了,将 (i)(pre_i) 的贡献放在 (pre_i) 的位置,那么这个区间查询的答案就是 (lsim r) 中记录的贡献的最小值了.

    可是直接这样搞可能会导致 (i) 在区间外 (pre_i) 在区间内的情况出现,那么就考虑将查询离线下来,按右端点排序,只有当 (ileq right) 时才将贡献放在 (pre_i) 上.

    代码

    #include<bits/stdc++.h>
    #define REP(i,first,last) for(int i=first;i<=last;++i)
    #define DOW(i,first,last) for(int i=first;i>=last;--i)
    using namespace std;
    const int MAXN=5e5+5;
    const int INF=1e9;
    int n,m;
    int arr[MAXN];
    struct Sor
    {
    	int num,id;
    }sor[MAXN];
    bool Cmp(Sor a,Sor b)
    {
    	return a.num>b.num;
    }
    struct SegmentTree//一颗维护区间 min 的线段树
    {
    	int min;
    }sgt[MAXN*4];
    #define LSON (now<<1)
    #define RSON (now<<1|1)
    #define MIDDLE ((left+right)>>1)
    #define LEFT LSON,left,MIDDLE
    #define RIGHT RSON,MIDDLE+1,right
    #define NOW now_left,now_right
    void PushUp(int now)
    {
    	sgt[now].min=min(sgt[LSON].min,sgt[RSON].min);
    }
    void Build(int now=1,int left=1,int right=n)
    {
    	if(left==right)
    	{
    		sgt[now].min=INF;
    		return;
    	}
    	Build(LEFT);
    	Build(RIGHT);
    	PushUp(now);
    }
    void Updata(int place,int num,int now=1,int left=1,int right=n)//单点修改
    {
    	if(right<place||place<left)
    	{
    		return;
    	}
    	if(left==right)
    	{
    		sgt[now].min=num;
    		return;
    	}
    	Updata(place,num,LEFT);
    	Updata(place,num,RIGHT);
    	PushUp(now);
    }
    int Query(int now_left,int now_right,int now=1,int left=1,int right=n)//区间查询 min
    {
    	if(now_right<left||right<now_left)
    	{
    		return INF;
    	}
    	if(now_left<=left&&right<=now_right)
    	{
    		return sgt[now].min;
    	}
    	return min(Query(NOW,LEFT),Query(NOW,RIGHT));
    }
    #undef LSON
    #undef RSON
    #undef MIDDLE
    #undef LEFT
    #undef RIGHT
    #undef NOW
    int pre[MAXN];
    int last[MAXN];
    int answer[MAXN];
    struct Range
    {
    	int left,right,id;
    }range[MAXN];
    bool Cmp2(Range a,Range b)
    {
    	return a.right<b.right;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	REP(i,1,n)//离散化
    	{
    		scanf("%d",&sor[i].num);
    		sor[i].id=i;
    	}
    	sort(sor+1,sor+1+n,Cmp);
    	sor[0].num=sor[1].num-1;
    	int tot=0;
    	REP(i,1,n)
    	{
    		if(sor[i].num^sor[i-1].num)
    		{
    			++tot;
    		}
    		arr[sor[i].id]=tot;
    	}
    	REP(i,1,n)//处理 pre 数组
    	{
    		pre[i]=last[arr[i]];
    		last[arr[i]]=i;
    	}
    	REP(i,1,m)
    	{
    		scanf("%d%d",&range[i].left,&range[i].right);
    		range[i].id=i;
    	}
    	sort(range+1,range+1+m,Cmp2);//将查询的区间按右端点排序
    	int now=1;
    	Build();
    	REP(i,1,m)
    	{
    		while(now<=range[i].right)//将小于右端点的贡献放上
    		{
    			if(pre[now])
    			{
    				Updata(pre[now],now-pre[now]);
    			}
    			++now;
    		}
    		answer[range[i].id]=Query(range[i].left,range[i].right);
    		if(answer[range[i].id]==INF)
    		{
    			answer[range[i].id]=-1;
    		}
    	}
    	REP(i,1,m)//输出
    	{
    		printf("%d
    ",answer[i]);
    	}
    	return 0;
    }
    

    这个东西怎么搞在线 (mathcal{O}(mlog n))

    建可持久化线段树就好了.

  • 相关阅读:
    抽象类 接口 抽象方法 虚方法【基本说明】
    安装mongoDB
    django配置templates、static、media和连接mysql数据库
    python虚拟环境virtualenv下安装MySQLpython
    django中widget小部件
    django使用mongodb建表
    thinkphp5使用redis
    python虚拟环境virtualenv
    php开启redis扩展
    纯CSS的下拉菜单
  • 原文地址:https://www.cnblogs.com/Sxy_Limit/p/13126523.html
Copyright © 2011-2022 走看看