|
Pro1699 中位数 题解//阅读须知:请读完第六行后跳到主函数阅读,有利于理解程序。 //思路:建立一个最大为n/2+1的小根堆,将数据输入小根堆,若堆满就删除堆顶元素,直到数据全部输入。 //若n为偶数,则中位数为堆顶元素,否则中位数为堆顶元素与左孩子和右孩子间更小的那个元素的算数平均值,即(堆顶元素+左孩子与右孩子间更小的那个)/2 #include<iostream> #include<cstdio> using namespace std; int a[260000]; //定义小根堆a int n,s=0,b,t;//n:需处理数据数量,s:堆内元素数量,b:输入媒介(数据中转),t:未处理数据数量 void swim(int s)//上浮操作,变量s为需要进行上浮的数据,本函数用于插入 { while(s>1&&a[s]<a[s/2]) { swap(a[s],a[s/2]); s/=2; } } void push(int b)//插入数据 { a[++s]=b; swim(s); //此处s为要上浮的元素在堆中的下标,详见上浮函数swim } void jd()//建立小根堆a,此时a中包含了输入数据中前n/2+1个数据 { for(int i=1;i<=n/2+1;++i) { cin>>b; push(b); //将b插入至堆中,详见插入函数push } } void sink(int k)//下沉操作,k恒为1 { while(2*k<=n/2+1) { int j=2*k; if(j+1<=n/2+1&&a[j]>a[j+1]) { j=j+1; } if(a[k]<=a[j]) { break; } swap(a[k],a[j]); k=j; } } void pop()//删除数据 { a[1]=a[s--]; //将堆顶替换为堆底元素 sink(1); } int main() { freopen("median.in","r",stdin); freopen("median.out","w",stdout); cin>>n; jd(); //建堆,详见建堆函数jd t=n-(n/2+1); //计算未处理数据数量,以免在循环里计算导致超时 while(t) //当数据没有处理完时 { t--; //剩余数据-1 cin>>b; push(b); //将输入数据b插入堆中,详见插入函数push pop(); //将堆顶(下标最小的不可能为中位数的元素)删除,详见删除函数pop } if(n%2) //当n为奇数 { printf("%0.1f\n",1.0*a[1]); } else { printf("%0.1f\n",1.0*(a[1]+min(a[2],a[3]))/2.0); } return 0; } //Adam与GS53热心创作
题目1699 中位数
AAAAAAAAAAAAAAAAAAAA
![]()
2024-05-14 21:32:50
|
|
求 $\sum_{i=1}^{n} \phi(i^2)$ 基本上是裸的杜教筛 一个关于 $\phi$ 的性质:$$\phi(ij) = \frac{\phi(i)\phi(j)gcd(i,j)}{\phi(gcd(i,j))}$$ 证明:该式本质上是容斥,$\phi$ 的原式子是,当 $n = {p_1}^{c_1}\times {p_2}^{c_2} \times ··· \times {p_m}^{c_k}$ $\phi(n) = n \times \prod_{i=1}^{m} (1 - \frac{1}{p_i})$ 这里式子就表示为先把 $i$ 和 $j$ 的质因数乘上在除去 $i,j$ 的共同质因数,即 $\phi(gcd(i,j))$,最后再消掉 $gcd(i,j)$ 即可得到该式。 然后开始推式子: $$ \sum_{i=1}^{n} \phi(i^2) = \sum_{i=1}^{n} i \times \phi(i) $$ 不难发现该式等于 $\phi \cdot id$ $$ (\phi \cdot id) \ast id = \sum_{d\mid n} d * \phi(d) * \frac{n}{d} = n \times \sum_{d\mid n} \phi(d) = id^2$$ 我们设 $f(n) = n \times \phi(n),S(n) = \sum_{i=1}^{n} f(i)$ ,这里的 $id$ 与 $id^2$ 的前缀和都比较好求。 运用杜教筛公式可得: $$ S(n) = \sum_{i=1}^{n}i^2 - \sum_{i=2}^{n} i * S(\lfloor\frac n i\rfloor)$$ $$ = \frac{n(n+1)(2n+1)}{6} - \sum_{i=2}^{n} i * S(\lfloor\frac n i\rfloor)$$ 线性筛出前 $n^{\frac{2}{3}}$ 项,整除分块即可
题目3352 平方前缀和
AAAAA
![]()
2024-04-06 15:38:46
|
|
题目3827 举办乘凉州喵,举办乘凉州谢谢喵
![]()
2024-04-03 12:11:51
|
|
幸せな明日を願うけど 底なしの孤独をどうしよう もう うめき声しか出ない わたし ぎゅうぐらりん
强度最低的一集。 考虑一个点 $(p_1,...,p_k)$ 的距离应该怎么算。 不难发现只可能是他们奇/偶最短路的最大值。也就是在距离最大的点到达前,其他所有的点都在某条边上来回横条。 记 $f_{u,0/1}$ 表示点 $u$ 的偶/奇最短路,那么答案就是 $$\sum_{S=\{p_1,...,p_k\}}{\min(\max_{u\in S}(f_{u,0}),\max_{u\in S}(f_{u,1}))}$$ 既有min又有max,不是很好算。考虑min-max容斥,则答案为 $$\sum_S{\max_{u\in S}(f_{u,0})}+\sum_S{\max_{u\in S}(f_{u,1})}-\sum_S{\max_{u\in S}(\max(f_{u,0},f_{u,1}))}$$ 注意到三者完全等价,我们只考虑第一项。 考虑将 $u$ 按 $f_{u,0}$ 升序排序后依次扫,那么问题转化为: 每次往某个组加入一个点,求从每个组中各选出一个点的方案数。 预处理逆元,容易做到线性复杂度。
题目3559 [USACO21Jan Platinum]Sum of Distances
![]()
2024-03-29 22:04:35
|
|
观察题图可知,一个骑士能攻击到的格子与自己所在的格子异色,所以有一种摆法是都摆在同一颜色的格子上,把一条相互攻击的关系变为网络流路径,这样就将扔掉骑士转化为了求最小割 因为一个骑士能与多个骑士互相攻击,所以可以共用路径 建图如下: ·源点向每个黄格子连边,流量为1 ·每个黄格子向能攻击到的红格子连边,流量为∞
·每个红格子向汇点连边,流量为1 跑最大流求出最少扔掉几个骑士,答案为n^2−m−maxflow
题目746 [网络流24题] 骑士共存
AAAAAAAAAA
![]()
2024-03-29 21:56:51
|
|
あがいた梦を捨てて揺れる今日は眠って誤魔化せ 失くした言葉を知らないなら 各駅停车に乗り込んで
非常好凸包题,我不会一点。 首先尝试将答案写的形式化一点。令路径依次经过 $(i,a_i)$,则 $a_0=1,a_x=y,a_i\le a_{i-1}$,答案为 $$\sum_{i=1}^{x-1}{C_{a_i}}+\sum_{i=1}^{x}{(a_i-a_{i-1})i^2} =x^2y-1 +\sum_{i=1}^{x-1}{C_{a_i}-(2i+1)a_i} $$ 令 $f_{i,j}$ 表示 $a_i=j$ 时的最小答案,根据斜率优化,决策点应该在 $(j,c_j)$ 的下凸包在斜率 $2i+1$ 的切点。 而我们注意到,随着 $i$ 的增大,$2i+1$ 也增大,那么决策点会单调右移。 如果从 $f_{x,y}$ 开始倒序模拟决策过程,那么就是在 $1\sim y$ 的下凸包上,先找到斜率 $2x+1$ 的切点 $p$,之后不断在 $p$ 原地决策,直到 $2i+1$ 小于 $p$ 与 $p-1$ 之间的斜率后,决策点会变为 $p-1$,然后重复…… 注意到除了最开始的 $p$,再往后的决策是固定的,可以直接预处理贡献。而 $p$ 可以凸包二分求出,$p$ 的贡献也是容易计算的。
对于多组询问,注意到不同的只有 $y$ 的限制。考虑将询问离线挂到 $y$ 上,在维护到 $1\sim y$ 的凸包时计算答案。 时间复杂度 $O(q\log n)$。
题目3566 [USACO21Jan Platinum]Minimum Cost Paths
![]()
2024-03-29 21:45:20
|