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 }
以上是关于10.13 1.0考试 第二题 学数数 题解的主要内容,如果未能解决你的问题,请参考以下文章