概述
*C.Painting Machines
不好求得分为恰好为 i i i的排列个数,则考虑转化为求解得分 ≥ i geq i ≥i的排列个数 g [ i ] g[i] g[i], a n s = ∑ i = 1 n g [ i ] ans=sum limits_{i=1}^ng[i] ans=i=1∑ng[i]。
很容易得到得分
≤
i
leq i
≤i的有序排列个数
w
[
i
]
w[i]
w[i]:
1
,
n
−
1
∈
P
1,n-1in P
1,n−1∈P,而其它数差分后的值
∈
{
1
,
2
}
in {1,2}
∈{1,2}。因为操作次数是固定的,且
∑
1
+
∑
2
=
n
−
2
sum 1+sum 2=n-2
∑1+∑2=n−2,所以
1
,
2
1,2
1,2的个数也是固定的,设分别为
c
n
t
0
,
c
n
t
1
cnt_0,cnt_1
cnt0,cnt1,则
w
[
i
]
=
(
i
−
1
)
!
c
n
t
0
!
c
n
t
1
!
w[i]=dfrac{(i-1)!}{cnt_0!cnt_1!}
w[i]=cnt0!cnt1!(i−1)!
容斥求出所有得分 > i >i >i( ≥ i + 1 geq i+1 ≥i+1)的排列个数 ( ( n − 1 i − 1 ) − w [ i ] ) i ! ( n − i ) ! ({n-1choose i-1}-w[i])i!(n-i)! ((i−1n−1)−w[i])i!(n−i)!。
*D.Go Home
每次贪心选期望最大显然倒序做,DP的复杂度做不了,观察出以下性质:
考虑只剩下两个最远处的位置 l , r l,r l,r没到的状态:
-
如果它们在车的同侧,直接把车开过去即可。
-
否则假设 P a > P b P_a>P_b Pa>Pb,必然存在 T b = T a + d i s ( X a , X b ) T_b=T_a+dis(X_a,X_b) Tb=Ta+dis(Xa,Xb),所以在 a a a到达前, b b b一定会一直帮着 a a a,使得 T a T_a Ta尽量小,从而 T b T_b Tb尽量小。
可以倒序构造,维护 L , R L,R L,R,初始化 L = 1 , R = n L=1,R=n L=1,R=n,当 L , R L,R L,R在车的一侧时终止,否则若 P L ≥ P R P_Lgeq P_R PL≥PR,在到达 L L L前, L L L的意志完全代表 R R R的意志,于是 P L + = P R P_L+=P_R PL+=PR,然后 R − − R-- R−−, P L < P R P_L<P_R PL<PR的情况同理可得。
具体可以看一下代码
code from sigongzi
#include <iostream>
#include <cstdio>
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
int N;
int64 S,X[MAXN],P[MAXN],ans;
void Solve() {
scanf("%d%lld",&N,&S);
for(int i = 1 ; i <= N ; ++i) {
scanf("%lld%lld",&X[i],&P[i]);
}
int L = 1,R = N;
int dir = 0;
while(1) {
if(X[L] >= S) {ans += X[R] - S;break;}
if(X[R] <= S) {ans += S - X[L];break;}
if(P[L] >= P[R]) {
if(dir != 1) {dir = 1;ans += X[R] - X[L];}
P[L] += P[R];R--;
}
else {
if(dir != 2) {dir = 2;ans += X[R] - X[L];}
P[R] += P[L];L++;
}
}
printf("%lldn",ans);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
return 0;
}
*E.Inversions
统计合法全排列个数的方法:
设 c n t i cnt_i cnti表示 A ≥ i Ageq i A≥i的位置个数,考虑从大到小选数,方案数即 ∏ i = 1 n ( c n t i − ( n − i ) ) prodlimits_{i=1}^n (cnt_i-(n-i)) i=1∏n(cnti−(n−i))
枚举逆序对,强制 i < j , P i > P j i<j,P_i>P_j i<j,Pi>Pj,分类讨论:
- A i < A j A_i<A_j Ai<Aj,强制 A j : = A i A_j:=A_i Aj:=Ai,贡献为合法排列数 / 2 /2 /2
- A i ≥ A j A_igeq A_j Ai≥Aj,贡献为总排列数-(强制 A i : = A j A_i:=A_j Ai:=Aj后的合法排列数/2)
考虑按权值从大往小做,维护以位置为下标的BIT
从
c
n
t
=
0
cnt=0
cnt=0的地方切开分成若干段,每段中强制
A
i
:
=
A
j
A_i:=A_j
Ai:=Aj时,
c
n
t
A
j
+
1...
A
i
cnt_{A_j+1...A_i}
cntAj+1...Ai一段相当于乘上了
c
n
t
−
1
c
n
t
dfrac{cnt-1}{cnt}
cntcnt−1,注意判断区间存在
c
n
t
=
1
cnt=1
cnt=1的情况,
*F.01 on Tree
一种比较经典的贪心方式
设点 x x x子树内 0 0 0的个数为 f ( x ) f(x) f(x), 1 1 1的个数为 g ( x ) g(x) g(x),显然先走 f ( x ) g ( x ) dfrac{f(x)}{g(x)} g(x)f(x)最大的点
单点的情况是固定的,可以用大根堆存储,每次弹出堆顶点 i i i:
- 若 f a i = 0 fa_i=0 fai=0( i i i为根),则删去 i i i后继续弹堆
- 否则 f a i fa_i fai还没有走过,根据贪心走到 f a i fa_i fai后一定会立刻进入 i i i,贡献为 g ( f a i ) f ( i ) g(fa_i)f(i) g(fai)f(i),那么 i , f a i i,fa_i i,fai就是一体的了,并查集缩成一个点后重新压入堆
最后
以上就是感性黑猫为你收集整理的【Atcoder】AGC023 C-F简要题解的全部内容,希望文章能够帮你解决【Atcoder】AGC023 C-F简要题解所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复