战果
黄绿蓝紫,248 pts,rk 4,T3 双指针维护反了qwq,原因两个:样例太水,只给 3h。赛后略改过 T3,气死了,样例为啥这么水?
D1505 E-小梦的学术论文
简单二分答案0.0,非常板,没啥好讲的。秒了。
核心代码
int check(int k) {int h = 0;for(int i = 1 ; i <= n ; i ++) {if(a[i] >= k) h += b[i];}return h >= k;
}
D1506 F-小梦的糖果游戏
维护一个前缀 \(dp_{i,j}\) 和一个后缀 \(dp2_{i,j}\) 数组,两者都表示 \([1,i]\) 或 \([i,n]\) 中的数组成 \(j\) 的方案数。算出来后根据乘法原理相乘合并答案即可。
核心代码
memset(dp1 , 0 , sizeof(dp1));
memset(dp2 , 0 , sizeof(dp2));
in(n);
dp1[0][0] = dp2[n + 1][0] = 1;
int m = 0;
for(int i = 1 ; i <= n ; i ++) in(a[i]) , m += a[i];
for(int i = 1 ; i <= n ; i ++) {for(int j = 0 ; j <= m ; j ++) {dp1[i][j] = dp1[i - 1][j];if (j >= a[i])dp1[i][j] += dp1[i - 1][j - a[i]];dp1[i][j] %= mod;}
}
for(int i = n ; i ; i --) {for(int j = 0 ; j <= m ; j ++) {dp2[i][j] = dp2[i + 1][j];if (j >= a[i]) dp2[i][j] += dp2[i + 1][j - a[i]];dp2[i][j] %= mod;}
}
int ans = 0;
for(int i = 0 ; i <= n ; i ++) {for(int j = 0 ; j <= m ; j ++) {ans += dp1[i][j] * dp2[i + 1][j] , ans %= mod;}
}
D1507 G-小梦的物理小球
不知道是第几次赛时差点切蓝了 www
一眼期望 dp。求直接落到每个线段后的期望和,定义函数 \(f(x)\) 表示从横坐标 \(x\) 向下坠落落到的第一条线段或坐标轴。
得转换方程:
求得 \(2\) 关于 \(998244353\) 的逆元为 \(499122177\),这样可以处理分数取模。
难点在于 \(f(x)\),暴力思路是对线段按纵坐标排序,然后线性枚举,这么做的复杂度是 \(O(n^2+qn)\) 的,可以拿到 \(40\) 分。
考虑按纵坐标从小到大添加线段,标记区间 \([l,r]\) 的最高层线段,可以用线段树维护区间赋值,单点查询,注意需要离散化。
这样复杂度就降到了 \(O((n+q)\log n)\)。
在处理查询时需要求得其下落的第一个线段,因此需要重复一遍增加线段的步骤,从下往上枚举,根据查询的高度增加对应的线段,这里可以用双指针来维护。
具体实现并不困难,思路也不是很难想,夹杂了两到三个内容,评蓝没问题。