qsc round#2 喵哈哈村的排队(本辣鸡想七想八的,特写此博文给自己一个提醒)

该oj是qsc自己写的比赛,友情链接:http://qscoj.cn/

喵哈哈村的排队

发布时间: 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

 复制
6
10 8 5 3 50 45
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
",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("
");
 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("
");
33     }
34     return 0;
35 }
真题解
原文地址:https://www.cnblogs.com/wujiechao/p/6445873.html