CF 口胡笔记 2100Ct辑
只需要口胡CF题就行啦!(
从昨天起口胡 CF 按照洛谷通过人数排序的题单
这期我们来口胡 CF2100 Part 1 吧 ~
目录导航:
CF208E Blood Cousins
给定树上节点 \(a\) 和距离 \(p\),求有多少 \(b\) 节点满足 \(a\) 与 \(b\) 的 \(p\) 级祖先相同。
可以点分树。更简单的做法是启发式合并。
题解还有线段树合并的做法的,感觉很有趣。
CF343D Water Tree
树。 \(m\) 次操作。操作有 \(3\) 种:
1. 将点 \(u\) 和其子树上的所有节点的权值改为 \(1\)。
2. 将点 \(u\) 到 \(1\) 的路径上的所有节点的权值改为 \(0\)。
3. 询问点 \(u\) 的权值。\(1\le n,m\le 5\times 10^5\)。
重链剖分+线段树板题
看看题解吧,什么,\(O(n\log n)\) ?!
题解给了一道前置题目,那我们就先做这道前置题目吧:
[P2936 USACO09JAN] Total Flow S [展开]
\(\le 52\) 个节点,每个节点之间可能有多条水管。串联水管取流量最小的作为合并后的水管的流量。并联水管取流量之和为合并后的水管的流量。求 \(A\) 点到 \(Z\) 点的流量。
不就是 Floyd
吗,为什么是蓝题。看题解吧。
哦,原来还可以是网络流啊(
不过看评论区好像是树上差分的原题被吞了,所以现在的前置题目和本题没有一点关系/愤怒
对于本题:
看了题解代码,我惊为天人!!!
题解开了两颗线段树, T1
记录该节点被改成 \(1\) 的最晚时间, T2
记录该节点是 \(2\) 操作链上最底端的最晚时间。
scanf("%d %d",&op,&x);
if(op == 1)t1[dfn[x]:dfn[x]+size[x]-1]+=i;
else if(op == 2)t2[dfn[x]]+=i;
对于查询, \(1\) 操作查询该节点 \(1\) 操作的最晚时间, \(2\) 操作查询子树内最晚的操作时间。
else if(op == 3)printf("%d\n",t1[dfn[x]:dfn[x]]>t2[dfn[x]:dfn[x] + size[x] - 1]);
CF1187E Tree Painting
树。一个点被删除只能当这个点是第一个被删除或者有一个相邻的被删除点。删除时记录该点所在联通块大小 \(S_i\) ,找到一种删除点的顺序来最大化 \(\displaystyle\sum S_i\)。
好像是 dp ,但是不会。
看一下提示吧:
删除了第一个点后,剩下的就不影响权值了
噢噢噢噢好有意思,写一下代码吧
展开代码
#include<bits/stdc++.h>
using namespace std;
#define ff(i,l,r) for(auto i=(l);(i)<=(r);++i)
#define fi(l,r) ff(i,l,r)
#define lowbit(x) ((x)&(-(x)))
#define ll long long
#define ul unsigned ll
#define ui unsigned int
#define P 998244353
#define N 200005
#define M 400005
ll ans,f[N],g[N];
int siz[N],tot,fir[N],nxt[M],to[M],n;
void add(int x,int y){
nxt[++tot]=fir[x];
fir[x]=tot;
to[tot]=y;
}
void dfs1(int x,int fa){
siz[x]=1;
for(int e=fir[x];e;e=nxt[e]){
int u=to[e];
if(u==fa)continue;
dfs1(u,x);
siz[x]+=siz[u];
f[x]+=f[u];
f[x]+=siz[u];
}
}
void dfs2(int x,int fa){
ans=max(ans,f[x]+g[x]+n);
for(int e=fir[x];e;e=nxt[e]){
int u=to[e];
if(u==fa)continue;
g[u]=f[x]-f[u]-siz[u]+g[x]+n-siz[u];
dfs2(u,x);
}
}
int main(){
scanf("%d",&n);
fi(2,n){
int x,y;
scanf("%d %d",&x,&y);
add(x,y);
add(y,x);
}
dfs1(1,0);
dfs2(1,0);
printf("%lld\n",ans);
return 0;
}
一遍过,帅!
CF656D Rosetta Problem
题目描述是乱码,就不放了。
这道题太难了,根本不会做。看题解吧。
题解看完还是不懂,做不了一点/doge
CF620E New Year Tree
给出一棵 \(n\) 个节点的树,根节点为 \(1\)。每个节点上有一种颜色 \(c_i\)。\(m\) 次操作。操作有两种:
1 u c
:将以 \(u\) 为根的子树上的所有节点的颜色改为 \(c\)。2 u
:询问以 \(u\) 为根的子树上的所有节点的颜色数量。\(1\le n,m\le 4\times 10^5\),\(1\le c_i,c\le 60\)。
注意到颜色范围很小,开60个树状数组 (91MB
) 就行了。
看看题解吧。
oh,原来可以状压。我小丑了。
CF372C Watching Fireworks is Fun
一个城镇有 \(n\) 个区域,从左到右编号为 \(1\sim n\),每个区域之间距离 \(1\) 个单位距离。
有 \(m\) 个烟火要放,给定放的地点 \(a_i\),时间 \(t_i\),如果你当时在区域 \(x\),那么你可以获得 \(b_i - \vert a_i - x\vert\) 的开心值。
你每个单位时间可以移动不超过 \(d\) 个单位距离。
你的初始位置是任意的(初始时刻为 \(1\)),求你通过移动能获取到的最大的开心值。
\(1\le n\le 1.5\times 10^5\),\(1 \le m \le 300\),\(1\le d,a_i\le n\),\(1\le t_i,b_i\le 10^9\)。
感觉是 \(O(nm)\) 的。
\(f[t][i] = \Big\downarrow\left\{\big\downarrow_{j=a_i-d}^{a_i}\left(f[t-1][j] - j\right) - b_i + a_i,\big\downarrow_{j=a_i+d}^{n}\left(f[t-1][j] + j\right) + b_i - a_i\right\}\)
可以用单调栈。 \(O(nm)\)。
CF837D Round Subset
\(n\) 个数 \(a_{1 \sim n}\) 中选 \(k\) 个让乘积的后缀 \(0\) 最多。
\(1 \le k \le n \le 200 , 1 \le a_i \le 10^{18}\)
这是一个 minmax 问题,注意到 \(n\) 很小,因数 \(2\) 和 \(5\) 出现的也很少( \(60\) 个 \(2\) )。记状态 \((i,j,x,y)\) 代表前 \(i\) 个数里选 \(j\) 个数,\(2\) 的个数为 \(x\) ,\(5\) 的个数为 \(y\) 。那么就可以设 \(f[i][j][y] = \max{x}\) 。复杂度 \(O(n^2\log_5^{1 \text{e} 18})=2\,060\,174\) 。
CF519E A and B and Lecture Rooms
树上询问两个点 \(x,y\) ,求到 \(x,y\) 距离相等的点的数量。 \(m\) 次询问。
\(1 \le m,n \le 10^5\)
设 \(x\) 和 \(y\) 的路径中点为 \(z\) 。如果 \(z\) 不存在( \(dis(x,y)\) 为奇数),那么数量为零。
否则记与 \(z\) 相邻的点为 \(u\) ,答案即为 \(x,y\) 所不在的 \(u\) 树大小之和 \(+ z\) 点。
CF609E Minimum spanning tree for each edge
给定一个无向图,求出必须包括 \(i\) 号边时的最小生成树。 \(i:1\sim n\);
\(1\le n,m \le 2\times 10^5\)
简单题,略。
CF1207F Remainder Problem
给你一个长度为 \(500000\) 的序列,初值为 \(0\) ,你要完成 \(q\) 次操作,操作有如下两种:
1 x y
: 将下标为 \(x\) 的位置的值加上 \(y\)2 x y
: 询问所有下标模 \(x\) 的结果为 \(y\) 的位置的值之和操作数 \(\leqslant500000\)
根号分治:
对于大于 \(\sqrt{5\text{e}5}=707\) 的数,\(2\) 操作的时候暴力统计。
对于小于等于 \(707\) 的数, \(1\) 操作的时候暴力维护。