复习与回顾:2021.7.10 contest 3
复习与回顾:2021.7.10 contest 3
A
Description
Alice
和 Bob
在玩石头剪刀布,他们每个人写出一个序列。 Alice 写出了 \(n\) 个数,Bob 写出了 \(n\) 个数。
其中 \(0\) 代表石头,\(1\) 代表剪刀,\(2\) 代表布 。
他们总共进行 \(k\) 轮游戏,第一轮选择第一个数字,后面每一轮两个人都选择序列的下一个数进行比赛(序列结尾的下一个位置在序列开头)。
一个人的积分为其赢的次数加上额外积分。
额外积分:对于每一个 \([1,k-x+1]\) 内的正整数 ,满足某人从第 \(i\) 轮到第 \(i+x-1\) 轮都赢,都会让这个人获得 \(1\) 的额外积分。
问 Alice
和 Bob
每人积分是多少。
Input
第一行三个数 \(n,m\) 。
第二行 \(n\) 个不大于 \(2\) 的非负整数。
第三行 \(m\) 个不大于 \(2\) 的非负整数。
Output
一行两个整数表示 Alice
和 Bob
每人积分。
Example
input
5 10 2
1 1 0 2 0
1 0 2 2 0
output
0 6
Hint
满足 \(1 \leq n \leq 5*10^5\ ,\ 1 \leq k,x \leq 10^{18}\)
Solution
由于两人给出的序列长度都是 \(n\) ,所以 \(n\) 就是循环节,特判 \(x \geq n\) 后枚举序列每个位置作为起始能不能得到额外积分,乘上每个位置能作为起始位置的次数。
Alice
和 Bob
分别计算一遍
B
Description
有 \(t\) 次询问,每次给你一个数 \(n\) ,求在 \([1,n]\) 内约数个数最多的数的约数个数。
Input
第一行一个正整数 \(t\) 。
之后 \(t\) 行,每行一个正整数 \(n\) 。
Output
输出 \(t\) 行,每行一个整数,表示答案。
Example
input
5
13
9
1
13
16
output
6
4
1
6
6
Hint
满足 \(t \leq 15\ ,\ 1 \leq n \leq 10^{18}\)
Solution
将 \(x \in [1,n]\) 进行质因数分解,则 \(x=\prod_{i=1}^{m}{p_i^{a_i}}\) ,而 \(x\) 的因数个数可表示为 \(\prod_{i=1}^{m}{(a_i+1)}\) ,发现与 \(p_i\) 大小无关,于是尽量把 \(p_i\) 往小取。
考虑爆搜,规定 \(p_i\) 与 \(p_{i+1}\) 是相邻的质数且 \(p_i < p_{i+1}\) ,要求 \(a_i \geq a_{i+1}\) 。发现跑最大数据比较吃力,于是记录 \(f_{i,j}\) 表示 \(p_i\) 为前 \(i\) 个质数,因数个数为 \(j\) 时的最小 \(x\) 来剪枝。
C
Description
给你一个长为 \(n\) 的序列 \(a\) 和一个常数 \(K\) 。
有 \(m\) 次询问,每次查询一个区间 \([l,r]\) 内所有数最少分成多少个连续段,使得每段的和都 \(\leq K\) 。
如果这一次查询无解,输出 "Chtholly",输出的字符串不包含引号。
Input
第一行三个数 \(n,m,K\) 。
第二行 \(n\) 个数表示这个序列 \(a\)。
之后 \(m\) 行,每行给出两个数 \(l,r\) 表示一次询问。
Output
输出 \(m\) 行,每行一个整数,表示答案。
Example
input
5 5 7
2 3 2 3 4
3 3
4 4
5 5
1 5
2 4
output
1
1
1
2
2
Hint
满足 \(1 \leq n,m \leq 10^6\ ,\ 1 \leq a_i,K \leq 10^9\) 。
Solution
考虑暴力,由于 \(a_i > 0\),从询问左端点开始每次贪心地取最长的满足限制的一段一定最优。发现除了最右的一段,每一段左端点对应的结束位置唯一确定,于是预处理后倍增加速这一过程,使复杂度降至 \(O((n+m)\,logn)\)
D
Description
给定一棵 \(n\) 个节点的树,第 \(i\) 个点的编号为 ,第 \(j\) 条边的编号为 \(j\) 。
有 \(m\) 次查询,每次给出 \(l,r\) ,查询如果只保留树上点编号在 \([l,r]\) 内的点,边编号在 \([l,r]\) 内的边,有多少点连通块,此时点 \(a\) 与 \(b\) 连通等价于 \(l \leq a,b \leq r\) 且 \(a,b\) 在树上的简单路径中所有点与边编号都在 \([l,r]\)之间。
Input
第一行两个数 \(n,m\) 。
之后 \(n-1\) 行,编号从 \(1\) 开始,第 \(i\) 行两个数 \(x,y\) 表示编号为 \(i\) 的边连接着点 。
之后 \(m\) 行,每行两个数 \([l,r]\) 表示询问区间 。
Output
对每次询问输出一行一个数表示答案。
Example
input
10 10
1 2
2 3
1 4
1 5
6 4
7 2
8 3
1 9
3 10
1 6
6 7
1 8
3 3
7 10
4 10
8 9
2 3
5 8
5 9
output
1
2
1
1
4
6
2
1
4
5
Hint
满足 \(1 \leq n,m \leq 10^6\)
Solution
对于一棵树的一个顶点子集\(V\)和边子集\(E\),定义一条边 \((u,v)\)为有效边当且仅当 \((u,v) \in E\ \ \bigwedge\ \ u,v \in V\) ,设有效边集合为 \(e\) ,则树的子图\(G=<V,E>\) 中的连通块个数等于 \(|V|-|e|\) ,证明显然。
对于询问区间 \([l,r]\ ,\ |V|=r-l+1\) 于是只需求 \(|e|\)
考虑编号 \(w\) 的边 \((u,v)\) ,其产生贡献当: \(l \leq w,u,v \leq r\ \ \Longleftrightarrow\ \ l \leq min\left\{w,u,v\right\}\ \bigwedge\ max\left\{w,u,v\right\} \leq r\)
我们将每条边转化为二元组 \((min\left\{w,u,v\right\}\ ,\ max\left\{w,u,v\right\})\) ,于是原问题转化为二维数点问题,用持久化线段树维护即可。
由于询问不强制在线,可以将询问离线后枚举左端点用树状数组维护各个右端点对应的答案,以此减少常数与代码量。
Code
int n,m;
vector<int>E[1000005];//在左端点存转化后离线的边
vector<int>Q[1000005];//在左端点存离线的询问编号
int QR[1000005];//询问的右端点
//以下是树状数组
int T[1000005];
inline void Push(int p){
for(;p<=n;p+=(p&-p))T[p]++;
}
inline int Get(int p){
int re=0;for(;p;p-=(p&-p))re+=T[p];return re;
}
//以上是树状数组
int Ans[1000005];
int main(){
Read(n);Read(m);
for(int i=1,x,y;i<n;i++){
Read(x);Read(y);
if(x>y)swap(x,y);
if(i<x)x=i;if(i>y)y=i;
E[x].push_back(y);
//边的转化与离线存储
}
for(int i=1,x,y;i<=m;i++){
Read(x);Read(y);
Q[x].push_back(i);
QR[i]=y;
//询问离线
Ans[i]=y-x+1;
//先加上|V|的贡献
}
for(int i=n;i>=1;i--){
for(int j=0,ed=E[i].size();j<ed;j++)Push(E[i][j]);
for(int j=0,ed=Q[i].size(),p;j<ed;j++){
p=Q[i][j];Ans[p]-=Get(QR[p]);//计算|e|
}
}
for(int i=1;i<=m;i++)
cout<<Ans[i]<<'\n';
return 0;
}
本文来自博客园,作者:蒻杨,转载请注明原文链接:https://www.cnblogs.com/weed-yang/