【线段树】HDU 5493 Queue (2015 ACM/ICPC Asia Regional Hefei Online)

题目链接:

  http://acm.hdu.edu.cn/showproblem.php?pid=5493

题目大意:

  N个人,每个人有一个唯一的高度h,还有一个排名r,表示它前面或后面比它高的人的个数,求按身高字典序最小同时满足排名的身高排列。

题目思路:

  【线段树】

  首先可以知道,一个人前面或后面有r个人比他高,那么他是第r+1高或第n-i-r+1高,i为这个人是第几高的。

  所以先将人按照身高从小到大排序,接下来,把当前这个人放在第k=min(r+1,n-i-r+1)高的位置。

  用线段树维护包含当前这个位置之前有多少个空,因为身高是递增的,所以前面已经放的都比当前这个人矮,而空的位置都将比这个人高,所以把这个人放在第k个空位置即可。

  1 //
  2 //by coolxxx
  3 //#include<bits/stdc++.h>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<string>
  7 #include<iomanip>
  8 #include<map>
  9 #include<stack>
 10 #include<queue>
 11 #include<set>
 12 #include<bitset>
 13 #include<memory.h>
 14 #include<time.h>
 15 #include<stdio.h>
 16 #include<stdlib.h>
 17 #include<string.h>
 18 //#include<stdbool.h>
 19 #include<math.h>
 20 #define min(a,b) ((a)<(b)?(a):(b))
 21 #define max(a,b) ((a)>(b)?(a):(b))
 22 #define abs(a) ((a)>0?(a):(-(a)))
 23 #define lowbit(a) (a&(-a))
 24 #define sqr(a) ((a)*(a))
 25 #define swap(a,b) ((a)^=(b),(b)^=(a),(a)^=(b))
 26 #define mem(a,b) memset(a,b,sizeof(a))
 27 #define eps (1e-8)
 28 #define J 10000
 29 #define mod 1000000007
 30 #define MAX 0x7f7f7f7f
 31 #define PI 3.14159265358979323
 32 #define N 100004
 33 using namespace std;
 34 typedef long long LL;
 35 int cas,cass;
 36 int n,m,lll,ans;
 37 LL aans;
 38 int s[N<<2],t[N];
 39 struct xxx
 40 {
 41     int h,r;
 42 }a[N];
 43 bool cmp(xxx aa,xxx bb)
 44 {
 45     return aa.h<bb.h;
 46 }
 47 void build(int l,int r,int k)
 48 {
 49     if(l==r){s[k]=1;return;}
 50     if(l>r)return;
 51     int mid=(l+r)>>1;
 52     build(l,mid,k+k);
 53     build(mid+1,r,k+k+1);
 54     s[k]=s[k+k]+s[k+k+1];
 55 }
 56 void change(int l,int r,int pos,int x,int k)
 57 {
 58     if(l==r){t[l]=x,s[k]=0;return;}
 59     if(l>r)return;
 60     int mid=(l+r)>>1;
 61     if(pos<=s[k+k])change(l,mid,pos,x,k+k);
 62     else change(mid+1,r,pos-s[k+k],x,k+k+1);
 63     s[k]=s[k+k]+s[k+k+1];
 64 }
 65 int main()
 66 {
 67     #ifndef ONLINE_JUDGE
 68 //    freopen("1.txt","r",stdin);
 69 //    freopen("2.txt","w",stdout);
 70     #endif
 71     int i,j,k;
 72
 73 //    for(scanf("%d",&cass);cass;cass--)
 74     for(scanf("%d",&cas),cass=1;cass<=cas;cass++)
 75 //    while(~scanf("%s",s+1))
 76 //    while(~scanf("%d",&n))
 77     {
 78         printf("Case #%d: ",cass);
 79         scanf("%d",&n);
 80         for(i=1;i<=n;i++)
 81             scanf("%d%d",&a[i].h,&a[i].r);
 82         sort(a+1,a+1+n,cmp);
 83         build(1,n,1);
 84         for(i=1;i<=n;i++)
 85         {
 86             j=min(a[i].r,n-i-a[i].r);
 87             if(j<0)break;
 88             change(1,n,j+1,a[i].h,1);
 89         }
 90         if(i<=n){puts("impossible");continue;}
 91         for(i=1;i<=n;i++)
 92             printf("%d%c",t[i],(i==n)?‘\n‘:‘ ‘);
 93     }
 94     return 0;
 95 }
 96 /*
 97 //
 98
 99 //
100 */

时间: 2024-08-23 22:37:07

【线段树】HDU 5493 Queue (2015 ACM/ICPC Asia Regional Hefei Online)的相关文章

(并查集)Travel -- hdu -- 5441(2015 ACM/ICPC Asia Regional Changchun Online )

http://acm.hdu.edu.cn/showproblem.php?pid=5441 Travel Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 2061    Accepted Submission(s): 711 Problem Description Jack likes to travel around the wo

(线段树 区间查询)The Water Problem -- hdu -- 5443 (2015 ACM/ICPC Asia Regional Changchun Online)

链接: http://acm.hdu.edu.cn/showproblem.php?pid=5443 The Water Problem Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 738    Accepted Submission(s): 591 Problem Description In Land waterless, w

【二分】【最长上升子序列】HDU 5489 Removed Interval (2015 ACM/ICPC Asia Regional Hefei Online)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5489 题目大意: 一个N(N<=100000)个数的序列,要从中去掉相邻的L个数(去掉整个区间),使得剩余的数最长上升子序列(LIS)最长. 题目思路: [二分][最长上升子序列] 首先,假设去掉[i,i+m-1]这L个数,剩余的LIS长度为max(i左端最后一个不大于a[i+m]的LIS长度+a[i+m]开始到最后的LIS长度). 所以,我们从n到1逆向先求最长下降子序列的长度f[i],就可以知

【动态规划】HDU 5492 Find a path (2015 ACM/ICPC Asia Regional Hefei Online)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5492 题目大意: 一个N*M的矩阵,一个人从(1,1)走到(N,M),每次只能向下或向右走.求(N+M-1)ΣN+M-1(Ai-Aavg)2最小.Aavg为平均值. (N,M<=30,矩阵里的元素0<=C<=30) 题目思路: [动态规划] 首先化简式子,得原式=(N+M-1)ΣN+M-1(Ai2)-(ΣN+M-1Ai)2 f[i][j][k]表示走到A[i][j]格子上,此时前i+j-1

【贪心】【模拟】HDU 5491 The Next (2015 ACM/ICPC Asia Regional Hefei Online)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5491 题目大意: 一个数D(0<=D<231),求比D大的第一个满足:二进制下1个个数在[s1,s2]范围内.D已经满足[s1,s2]. 题目思路: [贪心][模拟] 首先将这个数转成二进制统计总共1的个数s,再求出末尾连续0和1的个数n0,n1. 如果最后一位是0: s=s2,那么为了保证s<s2且答案>D,先设ans=d+lowbit(d),此时满足了新的s<s2且答案&g

HDU 5491 The Next 构造(2015 ACM/ICPC Asia Regional Hefei Online)

[链接]click here~~ [题意]: 给你一个D(0≤D<231),保证D的二进制中1的数量在s1和s2之间 然后让你求一个最小的数,使得这个数的二进制数量大于等于s1,小于等于s2,且大于 d [思路]虽然是比赛时候的一道水题,但是开始看到的时候并没有想到好的思路,最后还是学弟强行过掉,今天突然想到了可以用lowbit来求 首先看到D的范围是很大的,那么如何 构造呢? 这里举个例子:比如11,二进制表示(1011),取11+1=12,二进制表示(1100)s1=2,那么我们要做的就是考

(字符串处理)Fang Fang -- hdu -- 5455 (2015 ACM/ICPC Asia Regional Shenyang Online)

链接: http://acm.hdu.edu.cn/showproblem.php?pid=5455 Fang Fang Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 233    Accepted Submission(s): 110 Problem Description Fang Fang says she wants to be

HDU - 5491 The Next 2015 ACM/ICPC Asia Regional Hefei Online

从D+1开始,对于一个数x从它出发到x+lowbit(x)之前1的数量都是单调不减的,因此1的数量在一个范围内是一个区间. 每次判断一下有没有和[s1,s2]有没有交集. #include<bits/stdc++.h> using namespace std; inline int read() { char c; while(c=getchar(),c<'0'||c>'9'); int re = c-'0'; while(c=getchar(),c>='0'&&am

HDU 5489 Removed Interval 2015 ACM/ICPC Asia Regional Hefei Online

定义f[i]表示以i为开头往后的最长上升子序列,d[i]表示以i为结尾的最长上升子序列. 先nlogn算出f[i], 从i-L开始枚举f[i],表示假设i在LIS中得到的最长上升子序列,往[0,i-L)里找到满足ai>aj中dj值最大的.用dj+f[i]更新. 但是这样会少考虑一种情况,即i-L以后都不在最终的答案里面,这样一定是以[0~i-L)中的某个结尾的,所以还要用d[j]去更新答案. #include<bits/stdc++.h> using namespace std; con