【学习笔记】2021.10.6 - 清北学堂模拟赛
T1 区间第k大
题目内容
-
给定一个 \(1\sim n\) 的排列 \(\{p_i\}\) 以及整数 \(k\)。
-
对于每个 \(i \in [1,n]\),你需要求出该排列中有多少个区间 \([l,r]\) 的第 \(k\) 大恰好是 \(p_i\)。
-
输入一行 \(n\) 个整数,第 \(i\) 个整数表示有多少个区间以 \(p_i\) 作为第 \(k\) 大。
-
输出一行 \(n\) 个整数,第 \(i\) 个整数表示有多少个区间以 \(p_i\) 作为第 \(k\) 大。
Subtask1
\(n \leq 1000\)
思路
- 建一棵主席树,干就完了
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long ll;
const int MAXN(300233);
struct poi{
int ls,rs,sum,lt;
}tree[MAXN<<5];
int cnt,p[MAXN],n,kkksc03,rt[MAXN],ans[MAXN],cha[MAXN];
inline int R(){
int x=0;char c='c';
while(c>'9'||c<'0') c=getchar();
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x;
}
inline void BUILD(int OLD,int &NOW,int l,int r,int num){
NOW=++cnt;
tree[NOW].ls=tree[OLD].ls;
tree[NOW].rs=tree[OLD].rs;
tree[NOW].sum=tree[OLD].sum+1;
if(l==r) return;
int mid=(l+r)>>1;
if(num<=mid) BUILD(tree[OLD].ls,tree[NOW].ls,l,mid,num);
else BUILD(tree[OLD].rs,tree[NOW].rs,mid+1,r,num);
return;
}
inline int QUERY(int L,int R,int l,int r,int k){
if(l==r) return l;
int lsum=tree[tree[R].ls].sum-tree[tree[L].ls].sum;
// printf("l %d r %d mid %d k %d lsum %d Llssum %d Rlssum %d\n",l,r,(l+r)>>1,k,lsum,tree[tree[L].ls].sum,tree[tree[R].ls].sum);
int mid=(l+r)>>1;
if(k<=lsum) return QUERY(tree[L].ls,tree[R].ls,l,mid,k);
else return QUERY(tree[L].rs,tree[R].rs,mid+1,r,k-lsum);
}
int main(){
// freopen("ex_sequence3.in","r",stdin);
// freopen("my.txt","w",stdout);
n=R();kkksc03=R();
for(register int i=1;i<=n;++i) p[i]=R(),cha[p[i]]=i;
for(register int i=1;i<=n;++i) BUILD(rt[i-1],rt[i],1,n,p[i]);
for(register int i=1;i<=n-kkksc03+1;++i)
for(register int j=i+kkksc03-1;j<=n;++j)
// printf("QUE %d ~ %d:\n",i,j),
ans[cha[QUERY(rt[i-1],rt[j],1,n,j-i-kkksc03+2)]]++;
for(register int i=1;i<=n;++i) printf("%d ",ans[i]);
printf("\n");
return 0;
}
//打五把CS:GO!
期望得分 50pts
正解
思路
-
由于k固定,主席树真是太亏了!
-
考虑到只关心大小关系,我们可以预处理一个01数组,把比某位置大的赋值为1,反之为0,只需向前向后暴力拓展k个,然后计算即可。
-
复杂度 \(O(nk)\) 。
T2 染色
题目内容
-
有 \(n\) 个球排成一排,有 \(c\) 种颜色。这些球中有 \(m\) 个球已经染上了某种颜色。
-
你可以选择某个未被染色的球 \(i\),以及与它相邻且已被染色的球 \(j\),将球 \(i\) 染成球 \(j\) 的颜色。
-
当所有球都被涂上颜色后,设第 \(i\) 种颜色的球有 \(t_i\) 个。定义长为 \(c\) 的序列 \(\{a_i\}\) 满足 \(a_i= (t_i,i)\),其中括号表示有序对。
-
请求出对于所有可能的染色方案,序列 \(a\) 从大到小排序后字典序最大是多少。
-
两个有序对比较大小的方法为先比较第一个元素的大小,若相同再比较第二个元素的大小。
-
注意:\(c\) 种颜色不一定会全部出现在已经染好色的球中。
-
输入第一行三个整数 \(n,m,c\),分别表示球数,已染色的球数和颜色种数。
-
接下来 \(m\) 行,第 \(i\) 行两个整数 \(x_i,b_i\) 分别表示已染色球的位置和染的颜色。保证 \(x_i\) 严格递增。
-
输出输出 \(c\) 行,第 \(i\) 行两个正整数 \(x,y\) 表示答案序列(序列 \(a\) 从大到小排序后)的第 \(i\) 个有序对 \((x,y)\)。
Subtask1
\(n,m,c \leq 15\)
思路
- 贪心,每次扫一遍整个序列,按照第一关键字找到颜色最多的染色,第一关键字相同根据第二关键字不同进行染色。
代码
- 无QWQ
期望得分 20pts
Subtask3
\(m \leq 17\)
思路
-
枚举使用已经染色的球的所有方案,然后再进行处理即可
-
复杂度 \(O(2^m \times 17)\) 。
代码
- 无QWQ
期望得分 40pts
正解
思路
- 对于每个染了色的球建点,向未染色的段连边,边权为段的长度,最后求最大值和删边,考虑用大根堆,更改操作不用管,把新点扔到大根堆里即可,复杂度 \(O(c+m\log n)\) 。
代码
- 无QWQ
期望得分 100pts
T3 博弈论
题目内容
-
小T刚刚学习了博弈论的相关内容,他对 \(\rm mex\) 函数很感兴趣,于是想出了如下问题。
-
给定 \(n\) 个结点的树,结点编号为 \(1\sim n\),第 \(i\) 个结点上有点权 \(a_i\)。保证 \(\{a_i\}\) 为一个 \(0\sim n-1\) 的排列。
-
你需要对于每个 \(c\in [0,n-1]\),求出将每个点的点权 \(a_i\) 变为 \((a_i+c)\bmod n\),之后求出树上所有链的 \(\rm mex\) 值的最大值。
-
一条 \(u\) 到 \(v\) 的链的 \(\rm mex\) 值定义为这条链的点权构成的集合中,没有出现过的最小自然数(自然数包括0)。
-
注意:询问之间独立,也即每个询问的修改仅对当前询问有效。
-
输入:
-
第一行一个整数 \(n\),表示树的大小。
-
第二行 \(n\) 个整数 \(a_i\),表示点权。
-
接下来 \(n-1\) 行,每行两个整数 \(u_i,v_i\),表示一条树边 \((u_i,v_i)\)。
-
输出一行 \(n\) 个整数,第 \(i\) 个整数表示 \(c=i-1\) 时的答案。
正解
思路
-
先考虑 \(c=0\) 时的答案,此时要将 \(1 \sim n\) 依次加入直到不能形成链,使得mex最大。
-
维护链的起点 S 和终点 T ,若新加入的点正好在 S 或 T 上就直接把它挂上去。
-
若不是……
-
一会再说,先说一个重要的知识:
inline int LCA_OF_THREE(int x,int y,int z){
return lca(x,y)^lca(x,z)^lca(y,z);
}
//求三点LCA
-
多余的部分全都抑或抵消掉了,所以这是正确的。
-
后面的听不会了,人傻了,看Minus神仙的博客罢。
-
复杂度 \(O(n\log n)\) 。
代码
- 无QWQ
正解(超级加倍)
-
先讲一个技巧:双栈模拟队列。
-
就是让两个栈的栈底拼在一起,右栈往右移动时让右栈入栈,左栈弹栈,弹空了就把交界点的位置改变,防止GG。
-
剩下的仍然不会,看Minus神仙的博客罢。
T4 错排问题
题目内容
-
一个 \(1\sim n\) 的排列 \(p\) 被称为错排,当且仅当对于每个 \(i\) ,有 \(p_i \not= i\)。
-
给定整数 \(n,m\),你需要求出对于每个 \(k\in[0,m]\),满足 \(\sum_{i=1}^n|p_i-i|=k\) 且长为 \(n\) 的错排 \(p\) 有多少个。
-
由于答案很大,你只需要输出答案对 \(998244353\) 取模的结果。
-
输入一行两个整数 \(n,m\),表示错排长度和 \(k\) 的取值范围。
-
输出一行 \(m+1\) 个整数,第 \(i\) 个整数表示 \(k=i-1\) 时的答案对 \(998244353\) 取模的结果。
Subtask1
\(n \leq 10\)
思路
- 打表出省一。
代码
- 无QWQ
Subtask4
- 全程伞兵,弃疗了……