牛客网提高组第一场
这场比赛打得还是很满意的,起码第一题做出来了
标程与题解 密码:i25y
(1) 中位数
小\(N\)得到了一个非常神奇的序列\(A\)。这个序列长度为\(N\),下标从\(1\)开始。\(A\)的一个子区间对应一个序列,可以由数对\([l,r]\)表示,代表\(A[l], A[l + 1], ..., A[r]\)这段数。对于一个序列\(B[1], B[2], ..., B[k]\),定义\(B\)的中位数如下:
-
先对\(B\)排序。得到新的序列\(C\)。
-
假如\(k\)是奇数,那么中位数为\(C[\frac{k+1}{2}]\)。假如\(k\)为偶数,中位数为\(C[\frac{k}{2}]\)。
对于\(A\)的所有的子区间,小\(N\)可以知道它们对应的中位数。现在小\(N\)想知道,所有长度\(\geq Len\)的子区间中,中位数最大可以是多少。
输入描述:
第一行输入两个数\(N,Len\)
第二行输入序列\(A\),第\(i\)个数代表\(A[i]\)
输出描述:
一行一个整数,代表所有长度\(\geq Len\)的子区间中,最大的中位数。
示例1
输入
11 3
4864 8684 9511 8557 1122 1234 953 9819 101 1137 1759
输出
8684
备注:
数据范围:
\(30\)%:\(n \leq 200\)
\(60\)%😒 n \leq 2000$
另外有\(20\)%:不超过\(50\)个不同的数
\(100\)%:\(1\leq Len\leq n\leq 10^5, 1 \leq a[i] \leq 10^9\)
发现可以二分,那么把原序列排序一下,二分\(O(logn)\),然后再写一下\(O(n)\)的验证,就愉快的秒掉了这题
\(Code\ Below:\)
#include <bits/stdc++.h>
using namespace std;
const int maxn=100000+10;
const int inf=0x3f3f3f3f;
int n,len,a[maxn],sum[maxn],val[maxn],d[maxn];
inline int read(){
register int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return (f==1)?x:-x;
}
int check(int k){
for(int i=1;i<=n;i++)
if(a[i]<k) sum[i]=sum[i-1]-1;
else sum[i]=sum[i-1]+1;
d[0]=inf;
for(int i=1;i<=n;i++){
d[i]=min(d[i-1],sum[i]);
if(i>=len&&sum[i]>d[i-len]) return 1;
}
return 0;
}
int main()
{
n=read(),len=read();
for(int i=1;i<=n;i++) val[i]=a[i]=read();
sort(val+1,val+n+1);
int l=1,r=n,mid,ans;
while(l<=r){
mid=(l+r)>>1;
if(check(val[mid])) ans=val[mid],l=mid+1;
else r=mid-1;
}
printf("%d\n",ans);
return 0;
}
(2)数数字
小\(N\)对于数字的大小一直都有两种看法。第一种看法是,使用字典序的大小(也就是我们常用的判断数字大小的方法,假如比较的数字长度不同,则在较短一个前面补齐前导\(0\),再比较字典序),比如\(43<355\),\(10<11\).第二种看法是,对于一个数字,定义他的权值为,也就是各个数位的乘积。
现在给定两个区间,\([L,R]\)与\([L_1,R_1]\).小\(N\)现在想知道,有多少使用字典序判大小法在\([L,R]\)之间的数字,满足其第二种定义的权值也在\([L_1,R_1]\)之间。
换句话说,对于一个数\(x\),定义\(f(x)\)为\(x\)的各个数位的乘积。对于\(L\leq x\leq R\),问有多少\(x\)满足,\(L_1\leq f(x)\leq R_1\)。
输入描述:
第一行四个整数\(L,R,L_1,R_1\).
输出描述:
一行一个整数,代表小\(N\)想知道的数的数量。
示例1
输入
34 10000 24 57
输出
777
备注:
\(20\)%:\(L,R \leq 10000000\)
\(40\)%:\(L,R \leq 3\times 10^7\)
\(60\)%:\(L,R,L_1,R_1 \leq 10^9\)
另外有\(20\)%:\(L_1,R_1\leq 1000\)
\(100\)%:\(0\leq L,R,L_1,R_1 \leq 10^{18}\), \(L \leq R\), \(L_1 \leq R_1\)
数位\(DP\)
(3) 保护
C国有\(n\)个城市,城市间通过一个树形结构形成一个连通图。城市编号为\(1\)到\(n\),其中\(1\)号城市为首都。国家有\(m\)支军队,分别守卫一条路径的城市。具体来说,对于军队\(i\),他守卫的城市区域可以由一对二元组\((x_i,y_i)\)代表。表示对于所有在\(x_i\)到\(y_i\)的最短路径上的城市,军队\(i\)都会守卫他们。
现在有\(q\)个重要人物。对于一个重要人物\(j\),他要从他的辖区\(v_j\)出发,去到首都。出于某些原因,他希望找到一个离首都最近的,且在\(v_j\)到首都路径上的城市\(u_j\),使得至少有\(k_j\)支军队,能够全程保护他从\(v_j\)到\(u_j\)上所经过的所有城市。换句话说,至少有\(k_i\)支军队,满足在树上,\(x_i\)到\(y_i\)的路径能完全覆盖掉\(v_j\)到\(u_j\)的路径。
输入描述:
第一行输入两个数\(n\),\(m\).
接下来\(n-1\)行,每行两个整数\(u\),\(v\),表示存在一条从城市\(u\)到城市\(v\)的道路。
接下来\(m\)行,每行两个整数\(x\),\(y\).描述一个军队的守卫区域。
接下来一行一个整数\(q\).
接下来\(q\)行,每行两个整数\(v_j\),\(k_j\).
输出描述:
对于每次询问,输出从\(v_j\)到\(u_j\)最少需要经过多少条边。假如不存在这样的\(u_j\),则输出\(0\).
示例1
输入
8 8
7 1
1 3
3 4
4 6
6 2
4 5
7 8
7 2
7 1
7 1
7 5
1 1
1 3
1 6
5 1
8
5 1
2 1
2 1
4 2
3 2
4 2
1 1
4 1
输出
3
4
4
2
1
2
0
2
备注:
\(20\)%:\(n,m,q \leq 300\)
\(40\)%:\(n,m,q \leq 2000\)
\(60\)%:\(n,m,q \leq 50000\)
\(100\)%:\(n,m,q \leq 200000\)
树链剖分+主席树

浙公网安备 33010602011771号