杂题202509
20250909 杂题
CF961F k-substrings
binary search hashing string suffix structures *2700
对于每个 k-substrings,求出最大奇数 border。
肯定要尝试从其他 k-substrings 推出现在的结果。
注意到:若 \([i,n-i+1]\) 的答案是 \(x\),\([i+1,n-i]\) 的答案最小是 \(x-2\)。也即:
哈希判断字符串相等。
势能分析可知 \(O(n)\)。
CF620F Xors on Segments
data structures strings trees *2800
首先区间和变成前缀和没啥好说的。
特别的,这个前缀和其实可以 \(O(1)\) 求。
ds
考虑只有一个询问咋做?
一个简单的想法是,按照值大小将 \(s_{a-1}\) 加入 Trie 中,容易做到 \(O(n\log{V})\)。
考虑多个询问。要维护 Trie,不好扫描线了,考虑莫队。
还有一个问题是要保证 \(a\) 的大小关系。
考虑在 Trie 树上插入 \(s_{a-1}\) 时记录最小 \(a\)。
另开一个 Trie 插入 \(s_a\),记录最大 \(a\)。
但记录 \(a\) 就不好删除了,所以写回滚莫队即可。
\(O(n\sqrt{n}\log{V})\)。
dp
\(O(n^2)\) 是可行的。我们可以求出两两的结果,然后再做个区间扩展之类的东西就好。
但发现空间太大了。
考虑扫描线消去一维即可。
CF468D Tree
graph matchings *3100
首先考虑最大答案是多少。
将 \(\operatorname{dis}\) 的贡献拆开摊到每一条边上,就是在求 \((i,p_i)\) 分别在子树两边的个数。
可以知道答案应该有一个上界:假设断掉边 \(e(u,v) \in E\) 后形成的两个连通块分别为 \(e_1,e_2\),则答案不超过 \(2\sum_{e \in E} \min(|e_1|,|e_2|)\)。
我们把一个点 \(i\) 拆开成两个点 \(i\),\(i'\),\(p_i=j\) 等价于 \(i\) 和 \(j'\) 匹配。想要达到这个答案上界,当且仅当对于每一条边来说,其较小的那个连通块内部不存在匹配。
为了更好的表示出每个边的较小连通块,我们将重心视为树根,这样子每个边的较小连通块就是深度较大的那个。如此,前面的要求就可以更为简单的表示为与根相连的子树内部不存在匹配。可以视为每个点只能和对应子树外的点进行连边,是否存在完美匹配。
根据 Hall 定理,二分图存在完美匹配当且仅当对于任意点集其邻域点数更多。考虑到这张图同一个根子树内点具有相同的邻域,且选择任意两个不同根子树的点邻域为全集,可以表示为对于任意根子树 \(sz_u \leq n-sz_u\)。
由于重心满足 \(sz_u \leq \lfloor\frac{n}{2}\rfloor\),所以图一定有完美匹配。也即一定能达到答案上界。
考虑构造字典序最小的答案,点只能与根子树外的点连接,我们考虑何时贪心会出错。
还是 Hall 定理,我们将匹配视为同时删去两个点,判断剩下的点是否还有完美匹配。
考虑无论和时左右部点的个数是相等的,我们只需要对每个根子树考察是否满足 \(\text{树内左部点} \leq \text{树外右部点} = \text{剩余点数}-\text{树内右部点}\)。如果某棵树满足 \(\text{树内左部点} + \text{树内右部点} = \text{剩余点数}\) 就必须选这棵树了。(这里的剩余点数是左(或右部点)总点数)
CF891D Sloth
dfs and similar dp graph matchings trees *3100
断开后两种情况:
-
两块各自匹配
-
连接点是一个匹配
先考虑断边被确定了怎么做。对于断边后的两个连通块各自跑一遍 DP 求出有多少个点删去后有完美匹配 \(f\) 以及整个图是否有完美匹配 \(g\)。
若 \(g_u \wedge g_v\) 则答案是 \(sz_u \times sz_v\),否则是 \(f_u \times f_v\)。
考虑到转移方便,我们具体的设 \(f_{u,i,j}\) 表示 \(u\) 为根的子树,\(u\) 是否匹配,子树内(不算根)有无未匹配点的选点方案数。
转移时先将子树接到 \(u\) 上再进行合并,也就是枚举是否连向根。这样子合并的后两维是 \(\bmod x^2y^2\) 的转移形式,是交换,结合的。是交换,结合的就可以换根。
贡献类似最开始的 \(f,g\)。
CF442E Gena and Second Distance
geometry *3100
不能因为知道他是随机化而去随机化。
啊 不会做了。
首先一个明显的思路是二分答案。
考察一个 \(r\) 合法的条件。不太严谨的说:存在一个点,在这个点为圆心半径为 \(r\) 的圆内只有一个点。
(不严谨之处在于:没有区分圆上和圆内、圆上在园内没有点时可以有多个点等)
等价代换,我们从题目给出的点出发画半径为 \(r\) 的圆区域,若 \(r\) 合法则存在某个点在恰好一个圆的圆内(上),且在某个圆的圆上。
于是我们可以做到判定。具体过程是这样的:
-
枚举每一个题目给出的点
-
枚举其他点,并为其覆盖的圆弧段 +1
-
查询圆上是否存在 1
还有一个问题是如何在圆弧上修改?我们可以将圆弧视作一段极角区间,在上面维护差分即可。
实现求圆交点、求极角、差分。于是判定可以做到 \(O(n^2\log{n})\),加上二分就是 \(O(n^2\log{n}\log{V})\)。
差一点,能否作出一些剪枝优化复杂度呢。
考虑随机增量法。
具体来说,我们考虑每个给出点的最优 \(r\) 取 max。
对于随机序列,其期望严格前缀max的个数是 \(O(\log{n})\) 的。
于是我们先打乱序列,在对每个点二分之前先检查一次其是否能比当前答案更优,更优再二分,时间复杂度变为 \(O(n\log^2{n}\log{V}+n^2\log{n})\)。
确实懂了要咋做,但我不会求圆交点和极角啊
邪恶的计算几何,老夫这就亲手……。
CF786E ALT
data structures flows graphs trees *3200
网络流,优化建图。先咕着。
LGP2423 HEOI2012 朋友圈
图论 网络流 二分图 省选/NOI−
咕咕咕。
AGC004F Namori
基环树 >4000
可能不太严谨。
- 树
将树进行奇偶染色。原图中的白点在新图中和深度的奇偶性相同,黑点和深度的奇偶性相反。
问题变为通过交换树上两点使得树上所有点颜色取反。
所以有解条件就是黑白点个数相同。
考虑每条边的贡献。记黑点为 \(1\) 白点为 \(-1\),这条边的交换次数就是子树权值和的绝对值。(一次交换应当使得子树内实际权值和变化 \(2\),而我们希望令子树权值取反)
- 基环树
对于偶环基环树,仍然是二分图可以黑白染色。
视作把若干棵树的根串成一个环,先对每一棵树独立求解树权值。
然后有一些环上移动。记 \(x_i\) 表示 \(i\) 树向 \(i \bmod len + 1\) 传递的黑点数量,则应该有:
注意到这里的线性无关方程数目为 \(n-1\) 也即有一个自由元。我们钦定为 \(x_1\),则:
需要最小化 \(\sum|x|\),根据初中知识我们取 \(-\sum_{i=2}^{x}A_i(1 \leq x \leq n)\) 的中位数即可。
具体实现上,我们将断边后的根视为 1,底视为 2,那么就是除开根以外的环点贡献 A,根贡献 0.
还有就是奇环基环树。不满足二分图性质所以不能直接用上面的做法。要更细致的考察。
还是黑白染色,我们考察连接同色点的边,进行一次操作相当于创建/删除两个黑点。所以其存在意义就是改变两种点的个数使他们平衡。贡献是 \(A/2\)。
总而言之,结合上面的三种情况,得到了做法:
-
跑一遍树形 DP 求出 A
-
如果是偶环基环树,将环上 A 取出得到中位数,将环上加上这个数。
-
如果是奇环基环树,根据总树的 A 操作断边。
-
对 A 绝对值求和。
-
注意判无解。
UOJ#164 清华集训2015 V
线段树
-
区间加 \(a\)
-
区间减 \(a\),有下界
-
区间推平为 \(a\)
-
单点查询
-
单点查询历史最值
历史最值线段树问题。
我们发现操作都可以表示为 \(x \mapsto \max(x+a,b)\)(等价于 max+ matrix),这个操作有结合律,于是设计 Tag 对应上面的操作。
信息是当前值和历史最值,记作 \((0,x,y)\),考虑操作:
- 区间加 \(a\)
- 区间减 \(a\),有下界
- 区间推平为 \(a\)
矩乘经典问题:空间太大,常数太大。
观察到只有右上角四个数变了,推导一下:
确实没变。维护四个位置即可,常数大大减小。
小心 -inf 溢出!!!
小心 -inf 溢出!!!
小心 -inf 溢出!!!
小心 -inf 溢出!!!
小心 -inf 溢出!!!
小心 -inf 溢出!!!
在每次操作完对 -inf 取 max。
LGP2611 ZJOI2012 小蓝的好友
平衡树 深度优先搜索 DFS 栈 省选/NOI−
简单题。
至少包含一个点的矩形的数量,显然转化为不包含点的矩形数量。
先扫描线确定矩形左边界。
此时假设确定了上下边界,答案就是范围内最靠左的点的横坐标减去左边界坐标。
于是我们考虑构建每一列已扫描最靠左的点的笛卡尔树。
注意到位置为随机生成,树高不会超过 \(O(\log{n})\)。
直接类似 FHQ Treap 维护并动态统计答案即可。
问题在于如何动态确定点的区间数。
这个应该是和 \(l,r\) 有关的二元多项式,仔细分析可以发现下层只会加上来,所以次数不会发生变化,\(\operatorname{deg}(F) \leq 2\)。
还有个问题是初始化系数出现了 \(\frac{1}{2}\),于是我们维护 \(2\) 倍的多项式,最后答案除一下就好了。
\(O(n\log{n})\)。
额外题
ARC087F Squirrel Migration
CF468E Permanent
20250911 杂题
难度比上次低不少。
51Nod1851B 俄罗斯方块
简单题。
首先把行/列数存在 \(\leq 2\) 特判掉,这种会影响构造。
然后剩下发现都可以规约到一种结构:xx。
他是
x x
xx x
x xx
的叠合。由于行列数均大于等于 \(3\),所以可以在任意位置进行放置。
有意思的是,这个可以用于移动黑点以及消除成对的黑点。
(无端联想:想起昨天 Namori 那题了,Namori 是将同色反转变成异色移动+特殊边是同色反转)
所以如果图上有偶数个黑点一定有解,否则无解。
剩下的就是存在 \(\leq 2\) 了。
假设是个 \(1 \times n\),显然只能放 xxxx。
从前到后遇到黑就放就好了。
假设是个 \(2 \times 2\),只能放正方形,判一下就好。
假设是 \(2 \times n\),发现也可以放 xx。和前面一样。
LGP13687「DLESS-3」XOR and Rockets
动态规划 DP 位运算 提高+/省选−
拆位考虑。
序列有序,最高位一定有序,然后次高位按照最高位的 01 分界点划分为两个序列各自有序,如此递归下去。
操作 \(n\) 时,会将同一层全部不变/取反。可以得知同一层的所有序列要么同时升序,要么同时降序。
将这个 \(n\) 往前归纳,发现任何时刻都要满足这个性质。
于是设计 DP。根据上面讨论的内容,我们只需要知道:每一层是升序还是降序、最后一个元素是什么,信息量是 \(O(4^w)\),加上当前位置是 \(O(n4^w)\)。
我们可以等到转移时再对 \(i-1\) 进行操作,此时最后一个元素被位置所确定,信息量降为 \(O(n2^w)\),可以接受。
考虑设 \(f_{i,s}\) 表示操作完 \([1,i)\),前 \(i\) 个数的每一位是否降序。
但现在还有 \(O(2^w)\) 的转移因子,难以令人接受。
我们注意到,我们可以直接计算“不进行操作”的转移,这部分应该是 \(O(1)/O(w)\) 的。主要是要操作比较可恶。
考虑假设对 \(a_i\) 进行操作后,\(a_i\) 和 \(a_{i+1}\) 的最高不同位。显然更高位一定是确定且合法。检查一下当前这一位是否合法。更低位由于变成了“新开序列”也一定合法。
也即 \(i\) 向 \(i+1\) 转移应当是一段区间。
类似差分,我们打 tag 就可以优化到 \(O(w)\) 转移。
总时间 \(O(nw2^w)\)。
艹,看错题了。\(y\) 可以随便取任意正整数。
那剩下的部分修补一下就好。
现在我们考虑使用了操作 \(y \geq 2^{13}\)。显然一定有一次 \(x=n\),所以直接把 \(n\) 丢掉。
经典的,我们可以使用 \(y=2^{114514^{1919810}+k}\)。这样相当于直接把前面的序列丢掉。
处理和前面类似。
或者直接加上一维 0/1 表示是否使用这种情况即可。
完美!
然后发现被卡常卡烂了,我去这个出题人怎么这么坏啊。
不卡了,卡不动。
我去,怎么好像题解都是 \(O(n2^w)\) 的,这么牛。
先咕了,以后再想想能不能优化。
我去我怎么这么唐。
一个 \(O(n2^w)\) 的做法。
先放代码题解咕了。
#include<bits/stdc++.h>
// #define int long long
#define ll long long
const ll inf=1e16;
const int neg=(1<<13)-1;
using namespace std;
int n,a[5005],b[5005];
ll f[2][(1<<14)+5];
void tmain(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)cin>>b[i];
for(int i=0;i<(1<<14);i++)f[1][i]=(i!=a[n])*b[n];
for(int i=n-1;i>=1;i--){
swap(f[0],f[1]);f[1][(1<<14)-1]=inf;
for(int j=0;j<(1<<13);j++)f[1][j]=f[0][j]+b[i],f[1][(1<<14)-1]=min(f[1][(1<<14)-1],f[0][j|(1<<13)]+b[i]);
for(int j=neg-1;j>=0;j--)f[1][j]=min(f[1][j],f[1][j+1]),f[1][j|(1<<13)]=f[1][(j|(1<<13))+1];
for(int j=0;j<(1<<13);j++){
int v=a[i]^a[i+1]^j;
if(v<=j)f[1][v]=min(f[1][v],f[0][j]),f[1][v|(1<<13)]=min(f[1][v|(1<<13)],f[0][j|(1<<13)]);
}
}
ll ans=inf;
for(int i=0;i<(1<<14);i++)ans=min(ans,f[1][i]);
cout<<ans<<'\n';
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--)tmain();
}
AGC012C Tautonym Puzzle
2760
构造长度在 \(200\) 之内,字符集在 \(100\) 之内的字符串,满足恰有 \(N\) 个子序列可以表示为 \(AA\) 的形式。
有点牛啊这题。
前 100 个位置直接 \(1 \to 100\)。
后面的位置是 \(1\) 到 \(x\) 的排列,满足恰好有 \(n\) 个上升子序列(不算空串)。
从小到大插入,插入前面就是+1,插入后面就是*2.
感受那股劲:
#include<bits/stdc++.h>
long long n,nl=150,nr=149,nw=1,a[305],b[60],cnt;
signed main(){
std::cin>>n;n++;
while(n>1)b[++cnt]=n&1,n>>=1;
for(int i=cnt;i>=1;i--)a[++nr]=nw++,(b[i]&&(a[--nl]=nw++));
std::cout<<100+nr-nl+1<<'\n';
for(int i=1;i<=100;i++)std::cout<<i<<' ';
for(int i=nl;i<=nr;i++)std::cout<<a[i]<<' ';
}
CF717E Paint it really, really dark gray
dfs and similar *1900
直接搜有啥。
#include<bits/stdc++.h>
int n,a[200005];
std::vector<int> to[200005],ans;
void dfs(int x=1,int fa=0){
ans.push_back(x);
for(auto ed:to[x]){
if(ed==fa)continue;
dfs((a[ed]*=-1,ed),x);
}
if(fa==0)return void(((a[x]!=1)&&(ans.push_back(to[x][0]),ans.push_back(x),ans.push_back(to[x][0]),0)));
else{
if(a[x]==1)return void((a[fa]*=-1,ans.push_back(fa)));
else return void((ans.push_back(fa),ans.push_back(x),ans.push_back(fa)));
}
}
signed main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1,u,v;i<n;i++){
scanf("%d%d",&u,&v);
to[u].push_back(v);
to[v].push_back(u);
}
dfs();
for(auto ed:ans)printf("%d ",ed);
}
CF1019C Sergey's problem
constructive algorithms graphs *3000
旧题不表。
20250915-贪心构造
这个部分可能不严谨/证明缺失/证明错误。
LGP4404 缓存交换
贪心 省选/NOI−
首先肯定是先放入一段全部能放入前缀。
考虑冲突时要移除哪个。
贪心的想,应当移除下次出现时间更远的那个。
交了一发发现对了。
LGP5008 锦鲤抄
贪心 强连通分量 省选/NOI−
尝试了一下,我认为同一个 SCC 中的点应该是可以任意取的(当然,对于没有入度的 SCC 至少留下一个点。
首先环肯定是满足上述结论的。推广到 SCC 也应该差不多,大概就是考虑找一个有 SCC 外入度的点为终点,删掉这个点 SCC 内的所有入度,然后优先删除没有关键点出度的关键点。
所以在每个没有入度的 SCC 中扔掉一个最小的点,然后取 k 大即可。
交了一发发现错了。发现图存在自环。所以变成在每个没有入度和自环的 SCC 中扔掉一个最小的点。
交了一发发现对了。
LGP6122 Mole Tunnels
模拟费用流 省选/NOI−
注意到这是一个费用流模型。
将每个点和源汇点连边,和源点连边容量是鼹鼠个数,和汇点连边容量是 c,费用都是 \(0\)。然后原图边对应容量为 \(+\infty\),费用为 \(1\) 的边。答案就是最大流的最小费用(最小费用最大流)。
考虑模拟费用流。
每次添加一个鼹鼠,要考虑 \(s \to p_i \to y \to t\) 的一条增广路。肯定是尽量要走反边。
考虑维护 \(i\) 到三个邻接点的反边流量。然后把增广路径拆开成 \(x \to \operatorname{lca}\) 和 \(\operatorname{lca} \to y\) 两部分。每次增广的流量显然是 \(1\),于是我们维护一个 DP 表示从某个点向下走最小费用以及达到最小费用的点所在位置。每次从 \(p_i\) 开始暴力向根移动并将当前点作为 lca。取一个最小的出来暴力增广即可。
增广完记得更新一下 DP,显然只有 \(x \to rt\),\(y \to rt\) 的 DP 改变了。
注意到形如线段树的构图方式,树上路径长度为 \(O(\log{n})\),故时间复杂度为 \(O(n\log{n})\)。
LGP4694 PA 2013 Raper
模拟费用流 省选/NOI−
注意到这是一个费用流模型。
如果我们建图为 \(s \to i(1,a_i)\),\(i \to i+1(+\infty,0)\),\(i \to t(1,b_i)\),就是一个最小费用 \(k\) 流。
这里用到一个模拟费用流经典性质:费用是关于流量的凸函数。
考虑 WQS 二分去掉 \(k\) 的限制。
刻画单位流量 \(k\) 的惩罚,则可以 \(s \to i(1,a_i-k)\)。
现在变成一个最小费用任意流。
考虑增量费用任意流模型。我们可以假设一开始只存在 \(i \to i+1\),\(i \to t\) 的边,按照时间倒序加入 \(s \to i\) 的边。
这样,新的负增广路径只有 \(s \to i \to i+\delta \to t\),新的负环只有 \(s \to i \to i+\delta \to s\)。他们的费用分别是 \(a_i+b_j\) 和 \(a_i-a_j\)。(相当于反悔贪心,增加一对匹配和换掉一个不优的 \(a\))。
\(O(n\log{n}\log{V})\)。
LGP5633 最小度限制生成树
凸完全单调性(wqs 二分) 省选/NOI−
题意应该是先要求 \(s\) 有 \(k\) 条边,再要求权值最小。
是这么考虑的:首先先把 \(s\) 无关部分的 MST 跑了,然后考虑加入和 \(s\) 相连的边。显然若加入边后成环,我们贪心的换掉最大的边。
可以想到要先加入能产生负贡献(即让答案变小的边),此时答案会变小,然后再加边就尽量使得答案变大的慢一点。
虽然上面的策略是有点问题的(比如说 \(i\) 和 \(i+1\) 实际上使用完全不同的加边策略才能达到最优),但这仍然提示我们答案关于 \(k\) 成下凸。
于是考虑 WQS 二分去掉 \(k\) 的限制。去掉限制后显然是一个很基本的 MST 了。
\(O(n\log{n}\log{V})\)。
预先对 \(s\) 和非 \(s\) 点排序,此后使用归并合并,可以将复杂度优化到 \(O(n\log{V})\)。
LGP4983 忘情
凸完全单调性(wqs 二分) 省选/NOI−
今天第一道没有经过任何调试就通过的题目。
不知道式子写成这样有啥意义。严格弱于 JOIST 2023 Chorus。
随便改写一下:
然后不难写出一个状态数 \(O(nm)\) 的 DP:设 \(f_{i,j}\) 为前 \(i\) 个分成 \(j\) 段的最小值。
转移不难做到 \(O(n)\)。
显然状态数更加迫切需要优化,考虑优化掉第二维。
注意到 \(w(l,r)=(1+\sum_{i=l}^{r}x_i)^2\) 满足四边形不等式:
根据经典结论,\(f_n(x)=f_{n,x}\) 是个下凸函数。
直接套 wqs 二分消去第二维。现在要考虑的就是:
有四边形不等式可以直接做到 \(O(n\log{n})\),还是太慢了。
求出 \(x\) 的前缀和 \(S\),得到:
直接斜率优化。
具体的,记 \(F_{j-1}=f_{j-1}+S_{j-1}^2-2S_{j-1}\),考虑转移最优点 \(j\),其满足:
维护的应当是下凸包,也即当 \(\Delta_i<\Delta_j\) 时弹出。
可以做到 \(O(n)\)。
由于是 WQS 二分,讨论一下相等时的保留情况即可。
\(O(n\log{V})\)。
CF436E Cardboard Box
data structures greedy *2600
这个部分是口胡意淫,不保证正确性,不保证可以实现。
一个直接的思路是视作一个分组背包,每个组有重量分别为 \(0,1,2\) 的物品,有各自的价值,望最小化价值且背包至少装入 \(w\) 的物品。
这样是 \(O(n^2)\) 的状态,\(O(n)\) 的转移。
我尝试将其进行图论建模,但没啥用,不过通过图可以注意到到达同一个点存在几条路径。例如 \(3=1+2=2+1\)。
启发我进行邻项交换。实际上就是考虑当:
时,\(2\) 应当优先于 \(1\) 选择 \(b\)。
这显然具有传递性,于是我们按照 \(a-b\) 从小到大排序。然后前面的都是 \(0/1\),后面的都是 \(0/2\),具有分界(连续)的性质。在一段前缀中,我们会根据 \(a\) 从小到大的选择 \(1\),在后缀中,我们会根据 \(b\) 从小到大选择 \(2\)。
直接暴力枚举分界点和 \(1\) 的个数,我们应该可以通过一些数据结构做到 \(O(n^2)/O(n^2\log{n})\)。
然后想到在不超过 \(w\) 前肯定是先把 \(2\) 的贡献视为 \(b/2\) 然后从小到大选的,这个过程可以用数据结构加速。
最后再分讨 \(O(1)\) 种情况应该就好了。最后应该可以做到 \(O(n\log^2{n})\) 之类的复杂度吧。
我找到了一篇思路相似的题解,来自 feecle6418 老师的做法。
从
直接暴力枚举分界点和 \(1\) 的个数,我们应该可以通过一些数据结构做到 \(O(n^2)/O(n^2\log{n})\)。
继续。
在一段前缀中,我们会根据 \(a\) 从小到大的选择 \(1\),在后缀中,我们会根据 \(b\) 从小到大选择 \(2\)
实际答案是这两个序列排好序后的前缀和特定的位置相加。考虑答案的二阶差分也即两个序列的差分非负,具有凸性。翻转平移不改变凸性,非负线性组合也不改变凸性,所以答案关于 \(p\)(选 \(1\) 的个数)下凸。
直接对每个位置三分,数据结构维护 \(k\) 小得到一个 \(O(n\log^2{n})\) 的大常数做法。
然后就是发现对于 \(\min f_i(p)\) 来说也是下凸的,所以整体进行三分即可,复杂度不变,常数很小。
关于这个整体下凸的证明?我也不会。
ARC073E Ball Coloring
2434
考虑全局最大值,钦定其放在蓝色。
考虑全局最小值。
- 在蓝色
蓝色的值已经固定,考虑红色的最优解。
假设我们已知红色的最小值 \(x\):
\(a \leq b < x\) 证明 \(x\) 不对。
\(a < x \leq b\) 只能选 \(b\)。
\(x \leq a \leq b\) 选 \(a\)。
我们按照 \(a\) 排序后,一定是一段前缀选 \(b\),一段后缀选 \(a\)。
维护前后缀 min/max 即可。
- 在红色
显然小的放红大的放蓝。
做完了。
CF802O April Fools' Problem (hard)
binary search data structures flows *2900
和 PA 2013 Raper 有啥区别?
连样例都一样。
CF573E Bear and Bowling
data structures greedy *3200
考虑一个简单的值域无关的 DP:\(f_{i,j}\) 表示前 \(i\) 个选 \(j\) 个的答案,可以做到 \(O(n^2)\)。
感性猜测 \(f_{i,j}\) 关于 \(j\) 应该是凸的,但这是错的,样例就不是。
正确的结论是:\(f_{i,j-1}+jc > f_{i,j}\) 是一段后缀。
这个结论不太懂,等搞懂了再来补。
然后剩下的问题就是平移和等差数列加,放到平衡树上就是插入和打 tag。
20250917 杂题
CF917D Stranger Trees
dp math matrices trees *2600
挺简单的。
给出一棵树,对于每个 \(k\) 计算与给出的树恰好共享 \(k\) 条边的 \(n\) 顶点带标号树的数量。
比较明显的是先考虑容斥变成钦定共享 \(k\) 条边。
考虑已知一些边会把独立的 \(n\) 个点变成一些连通块,要把连通块连成树。
这是经典的用 prufer 序列解决的问题。假设分成若干连通块分别为 \(a_1,a_2,\cdots,a_m\),方案数就是:
于是我们就可以考虑使用 DP 来维护钦定共享 \(k\) 条边后的连通块情况了,维护和根节点相连的连通块大小,我们不难在 \(O(n^2)\) 也即树上背包的复杂度内求出答案。
另外注意到容斥也可以一起做。断掉 \(k\) 条边一定形成 \(k+1\) 个连通块。可以加一维表示连通块个数。
但这样变成了两维背包,时间复杂度变成了 \(O(n^4)\),看起来不太健康,但是 \(n\) 只有 \(100\) 好像也能过。
Accepted 之后去看 tag,发现有个 matrix 就离谱。
哦,原来是 Martix-Tree Theorem。
不过正经的来说,这题 \(O(n^4)\) 应该不是下界。
WC 怎么有 \(O(n^2)\),有点牛啊。
CF715E Complete the Permutations
combinatorics fft graphs math *3400
发现自己几乎完全不会输入大于 \(O(1)\) 的数数题
考虑那个距离是什么。
对于任意交换,经典的做法是 \(n-c\),\(c\) 是两个排列对应的置换中环的个数。(把一个置换环消成 \(n\) 个自环的最小操作次数是 \(n-1\))
于是其实就是 \(\pi_A G = \pi_B\),求 \((\pi_A,G)\) 的个数满足 \(G\) 的环的个数等于 \(k\) 的个数。
到这就不太会做了。
(以下是经过整理后的文字,略去了一些思维过程)
其实上面那个模型不太直观,可以这样表述:
把 \(p_i\) 和 \(q_i\) 连边,形成 \(k\) 个环的填数方法。
由于有一些位置已经填了,图上会出现四种链:
\(p \to q\),\(p \to 0\),\(0 \to q\),\(0 \to 0\)。
首先处理第一类边,用个并查集处理一下。如果成环了就记录一下并删掉,没有成环就缩成一个点。记录一下新图的点数。
另外,把 \(p \to 0\) 和 \(0 \to p\) 先合并为 \(0 \to 0\)。
现在图上剩下三类边:\(p \to 0\),\(0 \to q\),\(0 \to 0\)。并且 \(\forall p \neq \forall q\),记三类边的个数分别为 \(m_1,m_2,m_3\)。
注意到一个事实,\(p \to 0\) 和 \(0 \to q\) 不能相邻放置,否则会出现 \(p \to 0 \to q\) 这样无法收尾的链。
于是 \(p \to 0\) 后只能放 \(p \to 0\) 和 \(0 \to 0\)。\(0 \to q\) 同理。
转换一下,\(p \to 0\) 前只能放 \(p \to 0\) 和 \(0 \to 0\),\(0 \to q\) 同理(其实这步可以直接由 \(p \neq q\) 得到)。
我们倒着连这两类边。以 \(p \to 0\) 举例,一种情况是一直连 \(p \to 0\) 连成环,一种是连到 \(0 \to 0\) 变成 \(0 \to 0\)。不难发现最终 \(0 \to 0\) 的个数不变。
假设连成环一共 \(i\) 个,方案数即为:
特殊的,若 \(m_3=0\),就必须全部用于成环,即 \(\begin{bmatrix}m_1\\i\end{bmatrix}\)。
前两个是在处理直连成环,然后我们把剩下的排序,每一个边可以选择后面的边或者是 \(0 \to 0\) 边。
\(0 \to q\) 的处理也是同理。
剩下 \(m_3\) 个 \(0 \to 0\)。我们先给他们填上第一位转化成 \(p_1\) 即可。
也就是 \(h_i=m_3!\begin{bmatrix}m_3\\i\end{bmatrix}\)。
全部卷起来即可。
暴力处理第一类斯特林数得到 \(O(n^2)\) 做法。
51nod1976 多边形划分
计算几何
计算几何都这么神秘的吗?
对于多边形上一点 \(P\),记 \(P+x\) 为 \(P\) 在多边形上顺时针移动 \(x\) 单位到达的点。
首先任选多边形上一点 \(P\),记 \(f(x)\) 表示直线 \(P+x \to P+x+C/2\) 两侧多边形的面积之差。
有 \(f(x) = -f(x+c/2)\)。
根据零点定理,\([x,x+c/2]\) 之间存在 \(x_0\) 使得 \(f(x_0)=0\)。
只需找到其中一个零点,二分(移动同号一侧,保证得到两点仍然异号)即可。
关于凸多边形面积计算:三角剖分即可。
LOJ#6341 区间 or 和
首先显然有一个 \(O(qn\log{n})/O(qn)\) 的做法,or 具有单调性,可以二分/双指针。
发现差一点,\(n,q \leq 50000\)。
再往下就是 \(n\log^{k}{n}\) 或者 \(n\sqrt{n}\log^{k}{n}\) 了。可以想想分块。
假设块长为 \(B\)。
首先是块内,一个简单的想法是维护所有长度下的最大 or 和。
容易有一个 \(O(B^2)\) 的做法。
再考虑到 or 的性质,单调不降以及本质不同的 or 和只有 \(O(\log{B})\) 个。
可以考虑枚举左端点再做二分,可以做到 \(O(B\log^2{B})\)。
我们倒着扫,对每个位置每个位维护后面第一个让这个位变成 \(1\) 的位置,排序并去重即为结果。\(O(B\log{V})\)。
考虑块间。我们在第一个块的块末进行统计。还是前面的结论,块内起点只有 \(O(\log{V})\) 个,块外终点也只有 \(O(\log{V})\) 个。倒着扫所有块并动态维护这 \(O(\log{V})\) 个数。容易做到 \(O(\frac{n\log^2{V}}{B})\),仍然双指针做到 \(O(\frac{n\log{V}}{B})\)。
于是 \(B=\sqrt{n}\) 就做到 \(O(n\sqrt{n}\log{V})\)。
LOJ#503 ZQC 的课堂
首先显然 \(x\),\(y\) 间是独立的,两个相同的子问题,接下来只考虑一维 \(x\)。
我们考虑 \(y_k=1+\sum_{i=1}^{k}x_i(0 \leq k \leq n)\),穿过 \(x\) 轴就是 \(\operatorname{sgn}(y_k) \neq \operatorname{sgn}(y_{k-1})\),\(\operatorname{sgn}\) 表示符号(正负)。
这个形式不好表达(并非不好,其实只是为了【数据删除】),可以改为 \(\min(y_{k-1},y_k) < 0 \wedge \max(y_{k-1},y_k) > 0\)。
差分变成 \(1-[\min(y_{k-1},y_k)>0]-[\max(y_{k-1},y_k) < 0]\)。
两个子问题相似,接下来只考虑 \([\min(y_{k-1},y_k)>0]\)。
记 \(z_k = \min(y_{k-1},y_k)\),要求 \(\sum_{k=1}^{n} [z_k>0]\)。
一个简单的方法是分块,块内对 \(z\) 排序。容易做到 \(O(n\sqrt{n}\log{n})\)。
我们发现这个方法对于本题还是太强了,可以处理任意位置加,可本题有指针移动的设定。
由于元素是一个个加入/退出后缀的,我们直接将上面的分块后块内排序改为对后缀排序,用平衡树快速维护即可。
LOJ#2393 门票安排
就是游客可以顺时针/逆时针走,问覆盖最多的点最少覆盖几次。
双最可以试试二分答案。问题就变成了判定每个点最多覆盖 \(k\) 次是否可行。
CodeChef-BINOMSUM Day Schedule
首先知道单次询问大概是 \(O(k)\) 的复杂度。
每天的变化其实就是 \(D\)。所以我们先来讨论 \(D\) 确定时。
其实直接写就好了:
第一个组合数表示选出 \(i\) 顿小餐各自的位置。小餐不能相邻所以预留 \(i-1\) 个空位插在每顿小餐后,\(2\) 是前两个小时(早餐-活动)。剩下都比较明显。
考虑到存在上指标求和,设 \(f(x)=\sum_{i \geq 0}\binom{k-1-i}{i}x^iA^{k-1-i}=\sum_{i \geq 0} f_i (x+1)^{\overline{i}}\)。
单次可以做到 \(O(k)\)。
问题主要是如何做级数变换。这是经典问题,利用多点求值 \(O(k\log^2{k})\) 的求出需要的 \(k\) 处点值,再 \(O(k\log{k})\) 的利用点值求出结果。
于是就是 \(O(k\log^2{k}+Qk)\)。
看了题解发现这个求点值可以利用原式的 DP 式矩阵快速幂 \(O(\log{k})\) 求一个点值。有点牛啊。
决定自己再推一下。
显然可以 \(O(\log{k})\) 求点值。
完全的代数推导,不需要注意到原式 DP。
我写的是三模数 NTT,需要九次 DFT。所以,在两多项式最大次数 \(n \leq 70\) 的时候跑暴力乘法就可以过了。
解释就是,注意到分式远端求值时多项式次数都在 \(2\) 左右,用 MTT 还是太浪费了。
CF938G Shortest Path Queries
简单题。
先不考虑修改操作。这是经典问题,利用并查集把环弄下来放到线性基里,我们可以在 \(O(\log{V})\) 单次回答。
考虑带修,发现加好做删很难。可以线段树分治。并查集方面用可撤销,线性基方面由于信息量较小,向下时直接暴力创建副本即可(相当于每个线段树节点维护线性基。
至于求出两点路径。直接在维护并查集时维护从当前点到 fa 指向的节点的路径的权值。
\(O(n\log^2{n})\),瓶颈在线性基 adjust。
CF886F Symmetric Projections
提示:存在大量不严谨内容,而且不保证是对的。
特判 \(n \leq 2\)。
根据平行线分线段成比例定理,考虑转化为每个点出发画斜率相同的直线,直线与 \(x\) 轴的交点和某个 \(x\) 轴上点成中心对称。
这个中心点显然决定于投影最靠边的两个点。
对于任意两点他们的投影点位置关系是分两段的。
可以想到最后就是分 \(O(n^2)\) 段,每段内投影点相对位置(左右关系)不变。
感性理解,由于速度不同,每个段应该最多一个答案。如果是偶数个点,就是第一个和最后一个点的中点以及第二个和倒数第二个点的中点重合时才有可能。奇数个点就是第一个和最后一个点的中点和第 \(\lceil \frac{n}{2} \rceil\) 个点重合时才有可能。根据这两个点的相对关系(左右关系)进行二分即可。
就是 \(O(n^3\log{V})\)。至于判 inf,直接暴力随机 check。
进一步考虑奇数时中心点,答案应该是 \(O(n)\) 个的,偶数个大概也差不多。要想如何快速跳过假的段。
不会了。
以下是看题解没看完回来写的,所以还是不保证是对的。
看题解知道了“重心”性质。于是这个就是简单题了。
有了重心就容易确定 \(O(n)\) 个可能答案了(考虑奇数中心点和偶数 \(1\) 点配对)。
具体来说,有解则点不完全重合,一定有一个点和重心相离。
于是,他要么重合重心要么产生配对。
做完了。
发现考虑奇数时中心点之前推出的东西几乎没半点用,很绝望了。
还剩一些题题解明天再写。
20250916 51nod杂题
相对简单。
51nod-1243 排船的问题
所用到的最长的绳子最短
经典的双最问题,考虑二分答案。
贪心的想,每个船在限度范围尽量靠左放给后面腾出尽可能多的空间。
显然可以做到 \(O(n)\)。
其实一开始看错题了,以为是绳长总和最小,于是有了下面内容。
首先 -1 判掉以及 \(M \mapsto M-x\)。
我一开始的思路大概是调整,好像没啥前途。所以开始考虑 DP。
那么这个问题就是决策点间距离不小于 \(x\)。不难写出 DP:
按照 \(j\) 转移,注意 \(i\) 的行为就是前缀 \(\min\) 后再右移 \(x\)。
考虑 \(g_{i,j} = f_{i+jx,j}\),同时令 \(a_i \mapsto a_i - ix\):
这个 \(g\) 肯定是凸的。考虑 \(g_{x,0}=0\),下凸。前缀 \(min\) 保凸,凸加保凸,归纳得到结论。
只维护拐点斜率,\(O(nV) \to O(n^2)\)。
还有性质,绝对值函数只有两段斜率。两区间加,一个查找,一个推平。
随便线段树或者任何什么东西维护即可。
51nod-1461 稳定桌
考虑最终局面我们只关注最高的数目和总数目。不妨通过枚举得到最高高度。
此时可以得知最高数目 \(x\) 和小于最高的数目 \(y\)。
若 \(x \leq \lfloor \frac{x+y}{2} \rfloor\),容易计算出需要减少多少个小于。问题就是前 \(k\) 小代价和。
直接按高度排序,我们需要知道后缀 \(d\) 和以及前缀 \(d\) \(k\) 小和。
后缀和简单。
前缀 \(d\) \(k\) 小和最直接就是主席树,但是这题对于每个前缀只询问一次,所以任意数据结构都不难维护。
51nod-1611 金牌赛事
每段路有维修成本,如果 \(lb \sim ub\) 都修了就能获得 \(p\) 的报酬,求最大收益。
一个简单的思路是区间 DP,因为道路维修有连续性。每个区间可以做整区间维修或者是找一个点断开拆分下去,时间复杂度 \(O(n^3)\)。
可以考虑到维修是连续且不交的。考虑扫描线刻画区间右端点,维护左端点。假设只考虑前 \(i\) 个的答案是 \(f_i\),最后一段是 \([l,r]\) 的答案就是 \(f_{l-1} + w(l,r) - \sum_{i=l}^r c_i\)。
考虑到一个右端点 \(ub\) 后向 \([1,lb]\) 加上 \(p\),右端点每向右扩展一次就把 \([1,i]\) 减去 \(c_i\),计算出一个右端点 \(i\) 的答案后向 \([i+1,n]\) 转移 \(f\)(或者直接记录一下历史最大 \(f\),到点再更新即可)。
显然是 \(O(n\log{n})\)。
51nod-1593 公园晨跑
把小孩所在的位置删掉就变成链了。相当于是多个区间(链)询问。
莫队和扫描线好像都可以。
显然先把消耗变成 \((2h_x+dis) + 2h_y\)
扫描线的话就是扫右端点。保存出发点为 \(i\) 的信息。扫到 \(i\) 的时候给 \(i-1\) 加上 \(h_{i-1}\),然后给 \([1,i-1]\) 加上 \(d_{i-1}\),然后给 \([1,i-1]\) 加上 \(2h_i\) 再减掉,答案就是历史最大值。
莫队的话就维护区间内每个点到两端的 \(2h+dis\) 的最大值,向外扩展的时候更新答案,不太好删就回滚莫队即可。
51nod-1588 幸运树
树上两点肯定有唯一的路径吧。
每个边可以在最开始就可以确定是幸运边吧。
容易想到先枚举 \(i\)。至少经过一条幸运边的点数不太好,变成计算 \(n-c\),\(c\) 表示不经过幸运边的点数。答案就是 \(\sum_i (n-c_i)(n-c_i-1)\)。
\(c\) 的计算很简单。把所有非幸运边加入,形成的连通块大小就是 \(c\)。
51nod-1583 犯罪计划
注意是 所有 \(m\) 的乘积不超 123。
每个种类是独立的问题,以背包的形式组合成答案。
考虑一个种类的问题,我们希望找出其所有满足条件的 \(n\)。
首先将 \(m\) 去重,此时 \(m\) 至多剩下 \(5\) 个数。
可以暴力计算出 \([0,\operatorname{lcm})\) 范围内合法的数的集合 \(\mathcal{K}\),则合法的 \(n\) 就是 \(a\operatorname{lcm}+r,r \in \mathcal{K}\)。
也就是,我们只在意每个种类 \(\bmod \operatorname{lcm}\) 的结果。
可以状压在一起,然后矩阵快速幂就好。
51nod-1579 席位安排
又看错题了。不过两个问题都挺简单的。
字典序大概就只能从前往后决定了。大概问题就是给一个前缀,求这个前缀能补出多少种答案。
这个 \(N\) 的范围是可以状压的。直接 \(f_{s}\) 表示前 \(i\) 个放在 \(s\)。转移前缀中出现的数就特判。
显然是 \(O(2^{n}\operatorname{poly}(n))\)。
51nod-1533 一堆的堆
题面差评。
简单不等式得到 \(x\) 的父亲为 \(\lfloor\frac{x-2}{k}\rfloor+1\)。
固定上标(\(x-2\))后这玩意的取值只有 \(O(\sqrt{n})\) 个。取值相同则贡献相同。
差分维护每个 \(k\) 的答案,\(O(n\sqrt{n})\)。
51nod-1530 稳定方块
字典序比较肯定是靠前的优先。也就是说每步都是贪心的拿。
也就是说这题主要是考判定可不可以拿。
一次行动最多影响 \(5 \times 5\) 的范围(可以再精细但没必要)。
可以用 map 维护一个位置有没有值。
\(O(k^2m\log{m})\),\(k=5\)。
51nod-1528 加号分配
就是每个中间空位至多插入一个加号。其实就是划分这个数字串。
\(O(n^2)\) 是简单的,就是:
加法和加法显然可以单独考虑字串贡献,于是又可以写作:
这个 \(2^{i-2}\) 的含义是前 \(i-2\) 个数位后面都可以插入加号,\(i-1\) 后必须插入。另外一个同理。
当然有边界情况,严谨一点就是:
显然后面三项都可以在 \(O(n)\) 内完成,主要是第一项的求取:
预处理 \(2\) 和 \(5\) 的前或后缀和信息,可以 \(O(n)\) 求出。
51nod-1302 矩形面积交
一个弱化问题:不分组。显然是较短边一个方向,较长边一个方向(考虑最短的边确定了矩形一条边,最大化最长边)。
现在要分成两个组。先按照短边长度排序。枚举第二组的第一个元素,这之前的都放在第一组。
显然剩下的按照长边排序分两组放到两组之中。
所以还是 \(k\) 小和问题,随便写。
20250928 杂题
LOJ#2461 完美的队列
本来觉得是数颜色,不太可做。但是得到了一点提示。
由于询问一直是全体区间,所以实际上是在问那些线段没有完全失效。并不算完全的数颜色问题。
然后接下来的自己居然想出了一个做法。
如果只需要维护第一条线段到最后是否失效,一个不那么依赖线段的思路是先将每个位置的值附为 \(-a_i\),然后操作就是区间加,最后看线段所对应区间的最小值是否小于 \(0\)。
考虑这个方案的线段其实可以撤销,也就是区间减。于是我们可以扩展到维护全体线段到最后是否失效。就是求完第一条后区间减(或者更简单的,操作也是交换的,倒着做就好了)。
现在我们可以 \(O(nq)/O(nq\log{n})\) 了,不如暴力。
问题主要在于每个最终时间点都要判断。但是我们知道这个最终时间点是单调的,如果我们能快速判断一个时间点的可行性就很好做。
先扫描线按时间从后到前扫线段,然后考虑从当前线段出发向后。我们可以分块,维护 \(kS\) 到当前的所有线段加入的结果,这样我们只需要 \(O(S)\) 次扩展就可以完成任意时间点。扫描线移动时更新所有 \(Q/S\) 个终点。
时间复杂度就是 \(O(Q(\frac{Q}{S}+S)\log{n})\),取 \(S=\sqrt{Q}\) 做到 \(O(Q\sqrt{Q}\log{n})\)。
卡卡卡......卡过了?
虽然但是,不能因为卡过了就不写正经做法了。
学习了 WerKeyTom_FTD 老师和 lzqy_ 老师的做法,虽然都是半懂不懂,但还是总结出了一个做法。
我原来的思路其实很对,只是后面的维护比较唐。
还是从:
现在我们可以 \(O(nq)/O(nq\log{n})\) 了,不如暴力。
出发。
原来我的思路是对于每个询问快速找到最后有效时间点,这里也差不多。但是注意到:区间最后有效时间点等于区间内各个点的最后有效时间点的 \(\max\)。
所以我们开始考虑对序列而非时间进行分块,区间答案就是整块答案和散点答案的 \(\max\)。
然后仍然是倒着扫描线。
先考虑整块。考虑 two-pointer 的策略维护整块答案。可以直接像我之前的做法一样,整块维护线段树做区间加和区间求 \(\min\) 来判断是否可行。于是这部分可以做到 \(O(\frac{nm\log{n}}{S})\)。
WerKeyTom_FTD 老师指出这是不必要的。具体的,我们把修改放到要加入/退出的线段上考虑。线段应该会覆盖不超过 \(\frac{n}{S}\) 个整块和 \(2S\) 个散点。对于整块,我们维护一个整块操作标记,对于散点,我们暴力修改对应位置。整块操作可以做到 \(O(1)\),而散点操作在所有块维护中只会出现 \(O(mS)\) 次。此时总修改显然是 \(O(\frac{mn}{S}+mS)\) 的。
然后考虑散点。经过和 WerKeyTom_FTD 老师的讨论我了解了散点其实也可以 two-pointer。但是我的 two-pointer 有点区别(比较猎奇)。
具体的,考虑影响一个点的操作只有两种:这个点上的散点操作、这个点所在块的整块操作。
散点操作只有 \(O(mS)\) 个,如果我们对每个点维护指针并且让指针只指向散点操作复杂度就是对的。
我们在整块上记录这个整块的操作的所有位置,总信息量是 \(O(\frac{m^2}{S})\) 的。对每个点开一个 vector 记录这个点的散点操作,并记录每个散点操作前有多少次整块操作,总信息量是 \(O(mS)\) 的
然后我们考虑一次询问一个散点。首先我们尝试指针能否移动到下一个位置,相当于减去散点间整块个数加一之后是否大于 \(0\)。可以就暴力移动指针。
否则我们得出剩下需要撤销的次数,我们能 \(O(1)\) 的找出对应的整块操作/散点操作在哪,就可以回答了。
然后就没了。将 \(n,m\) 视为同阶,上述复杂度都是 \(O(NS)\) 或是 \(O(\frac{N^2}{S})\),可以做到 \(O(N\sqrt{N})\)。
30 pts MLE,祖传空超,但是跑得很快。
通过数组复用,块长调整得到 95 pts MLE。
块长大概 \(130\) 时散点数量和整块数量最平衡,空间最优。这份代码是我尽力卡空间的结果。
上面的做法瓶颈主要是存下 pt、sm、bk。
想到可以对于每个块分开跑,时间复杂度显然不变,只是会多 \(O(N\sqrt{N})\) 的开销。
但是就只用存下单个块的 pt、sm、bk 了。
其实整块和散块可以开两个数组然后一起处理,但是上面为了卡空间改掉了,就不改回来了,反正时间非常充裕。
并且这一版在 LG 上也能过了!
并且这份代码也可以不用玄学块长,\(\sqrt{N}=317\) 也能过!
完结撒花~~。
UOJ211 - 逃跑
显然,方差就是:
一个个解决。
\(E(X)\)
显然可以转成每个点有多大概率出现在路线上。
要么钦定第一次访问,要么钦定最后一次访问。这里钦定最后一次。
那就是前面过程随机游走,显然 \(n\) 步可以走到的坐标是 \(O(n^2)\) 的,可以 \(O(n^3)\) DP 暴力求出(后文记这个为 \(f\))。
后面的过程相当于从源点出发,不能走回原点的随机游走。这个也是容易 \(O(n^3)\) 的,就是在前面那个 DP 的基础上在线的去掉 \((0,0)\)(后文记这个为 \(g\))。
所以 \(E(X)\) 完全可以在 \(O(n^3)\) 解决。
\(E(X^2)\)
可以手动化开式子,也可以组合意义,都差不多是表达选出两个点都被路径经过的期望。
即 \(x^2 = x+2*\binom{x}{2}\)。\(x\) 的部分就是期望。主要是要解决 \(\binom{x}{2}\)
类似上面,我们把其中第一个点放在 \((0,0)\) 的位置,那就是从某个位置出发,走过 \((0,0)\) 和另外一个点的概率和。
假设在 \(t\) 时刻到达位置 \((0,0)\)(这里把定义修改为把其中最后出现的点放在 \((0,0)\) 的位置),已经经过另外一个点是 \((x,y)\),记为 \(h_{t,x,y}\)。
转移考虑钦定另一个点是最后一次,得到:
\(F_{t}\) 表示任何位置出发经过 \(t\) 时刻到达 \((0,0)\) 的概率和。比较显然的是从 \((x,y) \to (0,0)\) 等价于 \((0,0) \to (-x,-y)\),也即 \(F=\sum f=1\)。
还有求答案。就钦定 \((0,0)\) 最后出现的时刻 \(t\)。需要容斥掉的情况是 \((x,y)\) 在后面又出现了,钦定最后一次就好。
记从 \((0,0)\) 出发走 \(t\) 时刻不经过 \((0,0)\) 和 \((x,y)\) 的方案数为 \(w_{t,x,y}\):
\(G\) 表示 \((0,0)\) 出发经过 \(t\) 时刻到达任何位置,不重复经过 \((0,0)\) 的概率和。
有了这个答案就好求了。枚举最后时刻:
时间复杂度 \(O(n^4)\)。
感觉很有做半在线题的感觉。
这种问题主要是要充分利用已求出的信息。
CF860E Arkady and a Nobody-men
记 \(r(a,b)\) 为 \(b\) 子树中深度不比 \(a\) 深的点数。
记 \(z_a\) 为 \(a\) 的所有祖先 \(b\) 的 \(r(a,b)\) 之和。
求每个点的 \(z\)。
把贡献摊到每个点上就是计算 \(dep_{b} \leq dep_a\) 的 \(dep_{\operatorname{lca}(a,b)}\) 之和。
\(dep_{\operatorname{lca}(a,b)}\) 的一个比较经典的做法是对于所有的 \(b\),给 \(b\) 的所有祖先加上 \(1\),然后 \(a\) 计算所有祖先处的和。
然后就很简单了,树剖然后按照 dep 加入即可。做到 \(O(n\log^2{n})\)。
Time limit exceeded on test 36
吓得我看了眼题解,怎么是长剖 \(O(n)\)。但是好像也有树剖 \(O(n\log^2{n})\),好像要卡常(话说我写 zkw 还要卡常啊)。
换成 C++23 (GCC 14-64, msys2),加上 #pragma GCC optimize(2,3,"Ofast","inline") 就过了。
长剖明天再补。
CF873E Awards For Contestants
突然发现题单里还有 2300,直接先做这题。
先按照 \(i\) 排序。
直接枚举三个分界点是 \(O(n^3)\) 的。
不太必要枚举 \(3\) 和 \(-1\) 的分界,这个应该可以在低复杂度内完成。
根据限制 \(1\) 和 \(2,3\) 分界点得到这个点的取值范围,然后取一个最优的就好了。
数据结构维护出区间最优点 \(O(n^2\log{n})\)。
还可以写 ST 表优化查询到 \(O(1)\)。但是注意到我们允许 \(O(n^2)\) 预处理最大值。
所以就是 \(O(n^2)\)。
CF283E Cow Tennis Tournament
题目挺长的,先转化题意。
显然先离散化然后排序。
考虑何时 \(x\) 赢 \(y\)。记同时包含 \(x,y\) 的区间个数为 \(L_{x,y}\),则 \(L_{x,y} \equiv [x<y] \pmod{2}\)。
就是:包含 \(x,y\) 的区间如果有奇数个会把 \(x,y\) 取反。\(x<y\) 就要取反,否则不用。
即,对于 \(x<y\),\(x \to y\) 当且仅当 \(L_{x,y} \equiv 1 \pmod{2}\)。
然后计数图上的三元环。
三元环是不好做的,考虑容斥:不合法的三元环总是有且仅有一个点存在两个出度。
枚举这个出度为 \(2\) 的点,考虑剩下两个点。
相当于是在这个点的所有出度中选两个。
对于左边的个数就是 \(L_{x,y} \equiv 0\),右边就是 \(L_{x,y} \equiv 1\)。
容易扫描线扫出所有 \(y\) 时的 \(L_{x,y}\)。
CF750G New Year and Binary Tree Paths
- \(u\) 是 \(v\) 的祖先
先假设全部都是左儿子。
假设这条链上有 \(n\) 个点,链的标号和就是 \(\sum_{i=0}^{n-1} 2^{i} u=u(2^n-1)\)。
假如我们把其中一个点向左边走改成向右边走,那么下一个点的标号就会加 \(1\)。假设这个点下面还有 \(m\) 个点,增量就是 \(\sum_{i=0}^{m-1} 2^i = 2^m-1\)。
也就是说,根据我们不同的调整方法,我们的链长应当在:
注意到 \(2^n-n-1 < 2^n-1\),可以知道 \(s \in [u(2^n-1),(u+1)(2^n-1)) \Rightarrow u = \lfloor\frac{s}{2^n-1}\rfloor\)。
确定长度 \(n\) 就能确定顶点 \(u\),剩下的就是在 \(2-1 \sim 2^{n-1}-1\) 这 \(n-1\) 个中选若干个加起来等于定值 \(r\) 的方案数。
- \(u\) 不是 \(v\) 的祖先
运用类似的分析思路,假设 \(x = \operatorname{lca}(u,v)\),删去 \(x\) 之后变成长度为 \(n\),\(m\) 的两条链。取值范围分别是 \([2x(2^n-1),2x(2^n-1)+2^n-n-1]\) 和 \([(2x+1)(2^m-1),(2x+1)(2^m-1)+2^m-m-1]\)。
总取值:
\(2^n-n-1+2^m-m-1 < 2^{n+1}+2^{m+1}-3\),所以此时 \(x\) 也是固定的,有 \(x=\lfloor\frac{s-2^{m}+1}{2^{n+1}+2^{m+1}-3}\rfloor\)。
此时的问题是在 \(2-1 \sim 2^{n-1}-1\) 和 \(2-1 \sim 2^{m-1}-1\) 中选若干个加起来等于定值 \(r\) 的方案数。
两个问题都可以数位 DP 解决。
我们需要知道 \(r\) 有多少种方法表出。我们可以先假设选几个数,然后考察 \(r+k\) 被一堆 \(2^{w}\) 表出方案数。具体的,设 \(f_{i,j,k}\) 表示考察低 \(i\) 位选 \(j\) 个,是否进位且符合 \(r+k\) 的方案数。
状态数 \(O(\log^2{V})\),枚举 \(O(\log^3{V})\),总共就是 \(O(\log^5{V})\)。
P6272 湖北省队互测2014 没有人的算术
这个写了,但是晚点再补题解。总之就是重量平衡树。
还有几道题也写了,但是晚点再写。

浙公网安备 33010602011771号