10.13 1.0考试 第二题 学数数 题解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了10.13 1.0考试 第二题 学数数 题解相关的知识,希望对你有一定的参考价值。

技术分享

技术分享

技术分享

  这道题挺窝囊的……

  当时上来先打了一个n^2的暴力,期望40分。

  然后开始想正解,我先处理出来每个点是多少个区间的最大值,然后进行二分查找答案就好了,但是预处理时着实坑了我。

  一开始脑残,先打了O(nlog^2n)的预处理,先二分改点向右,向左第一个比他大的数,再在线段树里去搞,然后算了一下,貌似很有可能被卡常。当时也没管那么多,反正挺好打的,先打完再说。

  交上去之后突然想起来O(n log n)的打法,然后赶紧码了一下,达到一半发现之前忘记处理相同的情况了,急中生智,决定以下标为第二关键字,果然正确。交上去之后,突然又反应过来有的地方自己不爆int,但两数相乘是爆的,于是乎赶紧改了一下。全身冷汗……

  最后生怕出什么错,静态差错+对拍了半天,才放心的去做第三题。

技术分享
  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <queue>
  6 #include <algorithm>
  7 #include <cmath>
  8 #include <map>
  9 #define N 100005
 10 using namespace std;
 11 int n,q,a[N];
 12 char bb[50];
 13 int jg[12502505],zz;
 14 int get_bigger(int x)
 15 {
 16     if(x>=jg[zz])return zz+1;
 17     int li=1,ri=zz,mid;
 18     while(li<=ri)
 19     {
 20         mid=(li+ri)>>1;
 21         if(jg[mid]>x)ri=mid-1;
 22         else li=mid+1;
 23     }
 24     return ri+1;
 25 }
 26 int get_smaller(int x)
 27 {
 28     if(x<=jg[1])return 0;
 29     int li=1,ri=zz,mid;
 30     while(li<=ri)
 31     {
 32         mid=(li+ri)>>1;
 33         if(jg[mid]<x)li=mid+1;
 34         else ri=mid-1;
 35     }
 36     return li-1;
 37 }
 38 void work1()
 39 {
 40     for(int i=1;i<=n;i++)
 41     {
 42         int mx=0;
 43         for(int j=i;j<=n;j++)
 44         {
 45             if(a[j]>mx)mx=a[j];
 46             zz++;jg[zz]=mx;
 47         }
 48     }
 49     sort(jg+1,jg+zz+1);
 50     for(int i=1;i<=q;i++)
 51     {
 52         scanf("%s",bb);
 53         if(bb[0]==>)
 54         {
 55             int x;
 56             scanf("%d",&x);
 57             printf("%d\\n",zz-get_bigger(x)+1);
 58         }
 59         else if(bb[0]==<)
 60         {
 61             int x;
 62             scanf("%d",&x);
 63             printf("%d\\n",get_smaller(x));
 64         }
 65         else
 66         {
 67             int x;
 68             scanf("%d",&x);
 69             printf("%d\\n",get_bigger(x)-get_smaller(x)-1);
 70         }
 71     }
 72 }
 73 int dl[N];
 74 struct no
 75 {
 76     int left,mx,right;
 77 }node[N*4];
 78 void build(int left,int right,int x)
 79 {
 80     node[x].left=left,node[x].right=right;
 81     if(left==right)
 82     {
 83         node[x].mx=a[left];
 84         dl[left]=x;
 85         return;
 86     }
 87     int mid=(left+right)>>1;
 88     build(left,mid,2*x);build(mid+1,right,2*x+1);
 89     if(node[2*x].mx>node[2*x+1].mx)node[x].mx=node[2*x].mx;
 90     else node[x].mx=node[2*x+1].mx;
 91 }
 92 int get_right_down(int x,int z)
 93 {
 94     if(node[x].left==node[x].right)return node[x].left;
 95     if(node[2*x].mx>=z)return get_right_down(2*x,z);
 96     return get_right_down(2*x+1,z);
 97 }
 98 int get_right_big(int x,int z)
 99 {
100     if(x==1)return n+1;
101     if(x%2)return get_right_big(x/2,z);
102     if(node[x^1].mx>=z)return get_right_down(x^1,z);
103     return get_right_big(x/2,z);
104 }
105 int get_left_down(int x,int z)
106 {
107     if(node[x].left==node[x].right)return node[x].left;
108     if(node[2*x+1].mx>z)return get_left_down(2*x+1,z);
109     return get_left_down(2*x,z);
110 }
111 int get_left_big(int x,int z)
112 {
113     if(x==1)return 0;
114     if(x%2==0)return get_left_big(x/2,z);
115     if(node[x^1].mx>z)return get_left_down(x^1,z);
116     return get_left_big(x/2,z);
117 }
118 struct nod
119 {
120     long long l,r,bh;
121     long long data,da;
122 }nd[N];
123 long long sum[N];
124 bool px(nod a,nod b)
125 {
126     if(a.da==b.da)return a.bh<b.bh;
127     return a.da<b.da;
128 }
129 int get_big(int x)
130 {
131     if(nd[n].da<=x)return n+1;
132     int li=1,ri=n,mid;
133     while(li<=ri)
134     {
135         mid=(li+ri)>>1;
136         if(nd[mid].da>x)ri=mid-1;
137         else li=mid+1;
138     }
139     return ri+1;
140 }
141 int get_small(int x)
142 {
143     if(nd[1].da>=x)return 0;
144     int li=1,ri=n,mid;
145     while(li<=ri)
146     {
147         mid=(li+ri)>>1;
148         if(nd[mid].da<x)li=mid+1;
149         else ri=mid-1;
150     }
151     return li-1;
152 }
153 int main(){
154     scanf("%d%d",&n,&q);
155     for(int i=1;i<=n;i++)
156     {
157         scanf("%d",&a[i]);
158     }
159     if(n<=2000)
160     {
161         work1();
162     }
163     else
164     {
165         build(1,n,1);
166         for(int i=1;i<=n;i++)
167         {
168             nd[i].bh=i;
169             nd[i].l=i-get_left_big(dl[i],a[i]);
170             nd[i].da=a[i];
171         }
172         for(int i=1;i<=n;i++)
173         {
174             nd[i].r=get_right_big(dl[i],a[i])-i;
175             nd[i].data=nd[i].l*nd[i].r;
176         }
177         sort(nd+1,nd+1+n,px);
178         for(int i=1;i<=n;i++)
179             sum[i]=nd[i].data+sum[i-1];
180         for(int i=1;i<=q;i++)
181         {
182             scanf("%s",bb);
183             if(bb[0]==>)
184             {
185                 int x;
186                 scanf("%d",&x);
187                 int t=get_big(x);
188                 printf("%lld\\n",sum[n]-sum[t-1]);
189             }
190             else if(bb[0]==<)
191             {
192                 int x;
193                 scanf("%d",&x);
194                 printf("%lld\\n",sum[get_small(x)]);
195             }
196             else
197             {
198                 int x;
199                 scanf("%d",&x);
200                 printf("%lld\\n",sum[get_big(x)-1]-sum[get_small(x)]);
201             }
202         }
203     }
204     return 0;
205 }
View Code

以上是关于10.13 1.0考试 第二题 学数数 题解的主要内容,如果未能解决你的问题,请参考以下文章

9.5 考试 第二题 通讯题解

10.12 考试 第二题 乌鸦喝水题解

9.18考试 第二题Dinner题解

等级考试专题五:CSP-J 2020复赛第二题题解(桶排序的应用)

20170303

9.24考试总结