牛客网提高组第一场

这场比赛打得还是很满意的,起码第一题做出来了

标程与题解 密码:i25y

(1) 中位数

\(N\)得到了一个非常神奇的序列\(A\)。这个序列长度为\(N\),下标从\(1\)开始。\(A\)的一个子区间对应一个序列,可以由数对\([l,r]\)表示,代表\(A[l], A[l + 1], ..., A[r]\)这段数。对于一个序列\(B[1], B[2], ..., B[k]\),定义\(B\)的中位数如下:

  1. 先对\(B\)排序。得到新的序列\(C\)

  2. 假如\(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\)

树链剖分+主席树

posted @ 2018-09-11 08:36  Owen_codeisking  阅读(299)  评论(0)    收藏  举报