• 【解题报告】洛谷P7726 天体探测仪


    【解题报告】洛谷P7726 天体探测仪

    思路

    对于排列中的一个数字 (i) ,设以 (i) 为区间最小值的最长的区间是 ([l_i,r_i])

    首先考虑:如果已知 (l_i,r_i) ,如何求出来 (i) 的具体位置

    (len_i=r_i-l_i+1) 则对于某个 (j le len_i) 这段区间里面就一共有 (len_i-j+1) 个长度为 (j) 的子区间,如果所有长度为 (j) 的区间中都包括 (i) ,那么 (i)(S_j) 中就应该出现了 (len_i-j+1) 次,反之,它在这个集合中的出现次数小于 (len_i-j+1)

    因此,我们可以找到最大的 (j) 使得 (i)(S_j) 中出现的次数 (le len_i-j+1) 次,那么 (i) 到区间边界的距离就是 (j) ,也就是说,(i) 到区间边界的距离就应该是 (j) ,也就是说, (i) 的位置就是 (l_i+j) 或者 (r_i-j)

    这两个位置是等价的,因为区间整体反转一下也不会对答案产生影响

    我们发现上面的分析中只用到了 (len_i) ,而 (l_i,r_i) 仅仅用来定位,所以我们只要设法求出 (len_i) 就可以了

    (len_i) 就是使得 (i in S_k) 最大的 (k) ,容易求出

    实现的时候,我们首先求出来 (len_i)(i) 在以它为最小值的区间中的位置,然后从小到大扫描一个 (i) ,每次将 (i) 放到一个长度为 (len_i) 的没有用的区间中

    考虑如何维护这个闲置的区间呢?

    用一堆队列来维护所有长度为 (i) 的闲置区间的左端点,一开始的时候只有 (1 in q_n) 每次确定一个数字之后就会将一个闲置的区间分成两部分

    时间复杂度 (O(n^2))

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <string>
    #include <cstring>
    #include <queue>
    using namespace std;
    const int maxn=805;
    int n,k;
    int a[maxn];
    int seg[maxn][maxn];
    queue <int> q[maxn];
    int main()
    {
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n-i+1;j++)
    		{
    			int x;
    			cin>>x;
    			seg[i][x]++;
    		}
    	}
    	q[n].push(1);
    	for(int x=1;x<=n;x++)//枚举选择的数字 
    	{
    		int len=0;
    		for(int i=n;i>=1;i--)
    		{
    			if(seg[i][x]>0)
    			{
    				len=i;//找到一个长度为i的区间存在x 
    				break;
    			}
    		}
    		int k=0;
    		for(int j=1;j<=len;j++)
    		{
    			if(seg[j][x]==len-j+1)//看是否在某个区间的长度里面在所有的区间里面出现了 
    			{
    				k=j-1;//找到一个小于使得这个这个区间的长度 
    				break;
    			}
    		}
    		int l=q[len].front();//长度为len的可以放置的下一个区间的最小坐标 
    		q[len].pop();//取出第一个数字 
    		a[l+k]=x;//
    		if(k>0)//如果k的区间长度大于1的话 
    		q[k].push(l); //把这个东西放回去
    		if(len-k-1>0)//如果减去这个之后的区间长度大于1 
    		q[len-k-1].push(l+k+1);//那么更改放的位置,我们新的坐标改成这个 
    	}
    	for(int i=1;i<=n;i++)
    	cout<<a[i]<<" ";
    	cout<<'
    ';
    	return 0;
    }
    
    本博文为wweiyi原创,若想转载请联系作者,qq:2844938982
  • 相关阅读:
    虚拟机类加载机制详解
    简单了解Tomcat与OSGi的类加载器架构
    Java高并发编程(四)
    Java高并发编程(三)
    Java高并发编程(一)
    垃圾收集与几种常用的垃圾收集算法
    初识java内存区域
    vue2.0基础学习(1)
    git/github 生成密钥
    手机预览vue项目
  • 原文地址:https://www.cnblogs.com/wweiyi2004/p/15403639.html
Copyright © 2020-2023  润新知