zoukankan      html  css  js  c++  java
  • 【JZOJ5456】奇怪的队列【线段树】

    题目大意:

    题目链接:https://jzoj.net/senior/#main/show/5456
    题目图片:
    http://wx1.sinaimg.cn/mw690/0060lm7Tly1fwerg3tpiyj30jf0bigm3.jpg
    http://wx2.sinaimg.cn/mw690/0060lm7Tly1fwerg3u33aj30k40gz3yu.jpg

    给出nn个人的身高,第ii个人记得他的前面或者后面有a[i]a[i]个人比他高。这些人字典序最小的排列。


    思路:

    40分做法:

    先将所有人的身高排序,然后DFSDFS全排列,再判断是否成立。
    时间复杂度:O(n!n2)O(n!n^2)
    代码

    100分做法:

    按照样例一来模拟

    4
    4 1
    3 1
    6 0
    2 0
    

    先按身高排序(从小到大)

    4
    2 0
    3 1
    4 1
    6 0
    

    首先,我们有一个长度为4的空串
    在这里插入图片描述
    身高为2,前(后)面有0个人比他高的人。那么很明显,就只能插入第一个或最后一个位置。
    在这里插入图片描述
    为了字典序最小,那么就将这个人插入到第一个位置。
    在这里插入图片描述
    然后看下一个人,身高为3,前(后)面有一个人比他高。
    那么可能的位置也就只有一个,就插入三号位。

    在这里插入图片描述
    身高为4,前(后)面没有人比他高。
    那么剩余两个位置都有可能。
    在这里插入图片描述
    选择字典序更小的。
    在这里插入图片描述
    那么最后一个人就只能放在最后一个位置了。
    在这里插入图片描述
    那么,我们就需要一个可以插入和查找的数据结构。那么很容易想到权值线段树。
    然后就迎刃而解了。


    代码;

    #include <cstdio>
    #include <algorithm>
    #define N 100100
    using namespace std;
    
    int n,ans[N],f;
    char c;
    
    struct node
    {
    	int h,s;
    }p[N];
    
    struct Tree
    {
    	int l,r,num;
    }tree[N*3];
    
    int read()
    {
    	f=0;
    	c=getchar();
    	while (c<'0'||c>'9') c=getchar();
    	while (c>='0'&&c<='9')
    	{
    		f=f*10+c-48;
    		c=getchar();
    	}
    	return f;
    }
    
    void write(int x)
    {
    	if (x>9) write(x/10);
    	putchar(x%10+48);
    }
    
    bool cmp(node x,node y)
    {
    	return x.h<y.h;
    }
    
    void make(int x)  //建树
    {
    	if (tree[x].l==tree[x].r) 
    	{
    		tree[x].num=1;  //表示这个区间的空位的个数
    		return;
    	}
    	int mid=(tree[x].l+tree[x].r)/2;
    	tree[x*2].l=tree[x].l;
    	tree[x*2].r=mid;
    	tree[x*2+1].l=mid+1;
    	tree[x*2+1].r=tree[x].r;
    	make(x*2);
    	make(x*2+1);
    	tree[x].num=tree[x*2].num+tree[x*2+1].num;
    }
    
    void find(int x,int num,int h)  //查询
    {
    	tree[x].num--;  //空位减一
    	if (tree[x].l==tree[x].r)
    	{
    		ans[tree[x].l]=h;
    		return;
    	}
    	if (num<tree[x*2].num) find(x*2,num,h);  //可以往左就往左
    	else find(x*2+1,num-tree[x*2].num,h);
    }
    
    int main()
    {
    	n=read();
    	for (int i=1;i<=n;i++)
    	 p[i].h=read(),p[i].s=read();
    	sort(p+1,p+1+n,cmp);
    	for (int i=1;i<=n;i++)
    	 if (p[i].s>n-i)
    	 {
    	 	printf("impossible");
    	 	return 0;
    	 }
    	tree[1].l=1;
    	tree[1].r=n;
    	make(1);
    	for (int i=1;i<=n;i++)
    	 find(1,min(p[i].s,n-p[i].s-i),p[i].h);
    	for (int i=1;i<=n;i++)
    	{
    		write(ans[i]);
    		putchar(32);
    	} 
    	return 0;
    }
    
  • 相关阅读:
    比较器 Comparable 与compartor 的区别及理解
    事务特性、事务隔离级别、spring事务传播特性
    分布式文件上传-FastDFS
    spring-cloud 组件总结以及搭建图示 (六)
    springCloud zuul网关(五)
    hashCode与equals 通过面试题一窥究竟
    【原】那年30岁
    【原】Hyper-V虚拟机设置外部网络访问
    【原】win10 .net framework 3.5安装
    【原】做梦有感
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998504.html
Copyright © 2011-2022 走看看