qsc round#2 喵哈哈村的排队(本辣鸡想七想八的,特写此博文给自己一个提醒)
2017-02-26 21:05
162 查看
该oj是qsc自己写的比赛,友情链接:http://qscoj.cn/
描述
有一堆喵哈哈村的村民们在排队,他们从队列的尾部开始标号,标号为1的村民站在最后面,标号为n的村民站在队列的最前面,而且每个村民都拥有一个智商值a[i]。
这些村民有时候会觉得不开心,因为他们觉得凭什么一个智商比他低的人,可以站在他的前面!现在对于每个村民,他们都想知道,在他前面,智商比他低,离他最远的距离是多少。
输入
第一行n,表示有n只咸鱼
第二行n个整数,表示每个村民的智商值a[i].
n<=200000 1<=a[i]<=1000000000
输出
对于每个村民,输出智商比他的,且离他最远的距离是多少,如果没有输出-1
样例输入1 复制
样例输出1
然后真AC代码,及题解:
一个无脑的做法:对于每个人进行二分,二分之后用线段树取区间最小值或者一个其他的数据结构去维护就好了。
但实际上有其他的做法:
真题解
喵哈哈村的排队
发布时间: 2017年2月26日 16:13 最后更新: 2017年2月26日 16:14 时间限制: 1000ms 内存限制: 128M描述
有一堆喵哈哈村的村民们在排队,他们从队列的尾部开始标号,标号为1的村民站在最后面,标号为n的村民站在队列的最前面,而且每个村民都拥有一个智商值a[i]。
这些村民有时候会觉得不开心,因为他们觉得凭什么一个智商比他低的人,可以站在他的前面!现在对于每个村民,他们都想知道,在他前面,智商比他低,离他最远的距离是多少。
输入
第一行n,表示有n只咸鱼
第二行n个整数,表示每个村民的智商值a[i].
n<=200000 1<=a[i]<=1000000000
输出
对于每个村民,输出智商比他的,且离他最远的距离是多少,如果没有输出-1
样例输入1 复制
6 10 8 5 3 50 45
样例输出1
2 1 0 -1 0 -1 原本是水题来着,2333想七想八搞了个贪心+权值线段树+并查集,然后。。WA。贪心的策略根本不对好久才发现。最近真的是第K大做多了,思维同化。以下是WA代码给自己的提醒。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #define clr(x) memset(x,0,sizeof(x)) 6 using namespace std; 7 struct segtree 8 { 9 int val,num,l,r; 10 }tree[1000010]; 11 int a[200010],num[200010],fa[200010],afront[200010],n,m,l,r,k,rnu; 12 void init(int i,int l,int r); 13 void update(int i,int num); 14 int query(int i,int num); 15 int findpos(int i,int big); 16 int findposd(int num,int l,int r); 17 int Find(int i); 18 int main() 19 { 20 int n; 21 while(scanf("%d",&n)!=EOF) 22 { 23 clr(tree); 24 clr(afront); 25 for(int i=1;i<=n;i++) 26 scanf("%d",&num[i]); 27 memcpy(a,num,sizeof(num)); 28 sort(a+1,a+n+1); 29 for(int i=0;i<=n;i++) 30 fa[i]=i; 31 rnu=unique(a+1,a+n+1)-a-1; 32 init(1,1,rnu); 33 for(int i=n;i>=1;i--) 34 { 35 k=query(1,num[i]); 36 if(k!=0) 37 { 38 l=findpos(1,k); 39 // printf("%d %d\n",k,l); 40 fa[i]=Find(afront[l]); 41 } 42 afront[findposd(num[i],1,rnu)]=i; 43 update(1,num[i]); 44 } 45 for(int i=1;i<=n;i++) 46 { 47 if(num[Find(i)]!=num[i]) 48 printf("%d ",Find(i)-i-1); 49 else 50 printf("-1 "); 51 } 52 printf("\n"); 53 } 54 return 0; 55 } 56 void init(int i,int l,int r) 57 { 58 tree[i].l=l; 59 tree[i].r=r; 60 tree[i].val=a[r]; 61 if(l==r) 62 return ; 63 int mid=(l+r)>>1; 64 init(i<<1,l,mid); 65 init((i<<1)|1,mid+1,r); 66 return ; 67 } 68 void update(int i,int num) 69 { 70 tree[i].num++; 71 if(tree[i].l==tree[i].r) 72 return ; 73 if(tree[i<<1].val>=num) 74 update(i<<1,num); 75 else 76 update((i<<1)|1,num); 77 return ; 78 } 79 int query(int i,int num) 80 { 81 if(tree[i].val<=num) 82 return tree[i].num; 83 else 84 { 85 if(tree[i<<1].val<num) 86 return query(i<<1,num)+query((i<<1)|1,num); 87 else 88 return query(i<<1,num); 89 } 90 } 91 int findpos(int i,int big) 92 { 93 if(tree[i].l==tree[i].r) 94 return tree[i].l; 95 if(tree[i<<1].num>=big) 96 return findpos(i<<1,big); 97 else 98 return findpos((i<<1)|1,big-tree[i<<1].num); 99 } 100 int findposd(int num,int l,int r) 101 { 102 if(l==r) 103 return l; 104 int mid=(l+r)>>1; 105 if(a[mid]>num) 106 return findposd(num,l,mid-1); 107 if(a[mid]<num) 108 return findposd(num,mid+1,r); 109 return mid; 110 } 111 int Find(int i) 112 { 113 if(fa[i]!=i) 114 fa[i]=Find(fa[i]); 115 return fa[i]; 116 }
然后真AC代码,及题解:
一个无脑的做法:对于每个人进行二分,二分之后用线段树取区间最小值或者一个其他的数据结构去维护就好了。
但实际上有其他的做法:
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <algorithm> 5 #define MAX 200002 6 using namespace std; 7 8 int a[MAX],ans[MAX]; 9 vector<int> v,num; 10 11 int main() 12 { 13 int n; 14 while(~scanf("%d",&n)){ 15 for(int i=0;i<n;i++) scanf("%d",&a[i]); 16 v.clear(); 17 num.clear(); 18 for(int i=n-1;i>=0;i--){ 19 if(v.size()==0 || v.back()>=a[i]){ 20 v.push_back(a[i]); num.push_back(i); 21 ans[i]=-1; 22 }else{ 23 int j = (lower_bound(v.rbegin(),v.rend(),a[i]) - v.rbegin()); 24 j = (int)v.size() - j - 1; 25 ans[i] = num[j+1] - i - 1; 26 } 27 } 28 for(int i=0;i<n;i++){ 29 if(i) printf(" "); 30 printf("%d",ans[i]); 31 } 32 printf("\n"); 33 } 34 return 0; 35 }
真题解
相关文章推荐
- 给大家以及给自己的一个提醒
- 自己写的一个记录日常事务的小软件,也可以作为密码保险箱和提醒工具
- 对自己的一个自我提醒,人生路很远,不可走偏!
- 做了一个小软件用来提醒自己注意健康
- 一个老程序员PHP程序员说的话(谨以此片时刻提醒自己)
- 给自己一个提醒——读了这篇文章感觉目前就略有体会,但是它又是一个长期的过程。
- 提醒自己的一篇博文
- 一个VB小程序,提醒自己上下班打卡和每小时休息
- 周末发现一个BUG,时有时无,一出程序就崩溃,郁闷了好久,终于跟出来来了,记之,提醒自己今后一定规范编写,只要规范,绝对不会出问题
- 今天真是不在状态的一天,又是一个书写的错误(本文仅为提醒自己,你可以选择跳过)
- 这段程序还搞错一个输出(写在这里提醒自己)
- 制度化-给未来的自己发送一个提醒
- 使用多线程方法实现一个死锁程序,用来提醒自己不要犯这样的错误
- 一个程序员的过去10年的心得体会(时刻提醒自己)
- 每当我想查找一个我的博文的时候就想放弃CSDN,没有自己的搜索功能啊
- 还是犯了一个优先级的错误_sql,记录下,提醒自己
- 使用JavaBean创建您的网上日历本 有的朋友曾经说过,如果有一个网上的日记本,或者一个网上的万年历能提醒自己到时去干什么事情就好了。其实呀,这样的日历本您自己也能做一个。不信你看下面的例子: 〈
- 给Visual Studio 2005设置一个代码边界线,提醒自己,别写的太长哦。
- 在win+intel下面写代码总少不了这样那样的工具,这里做一个总结,提醒自己也给后来人方便。
- 编程之路,给自己一个方法,一个提醒