没错,这两天迷上了这个算法,这是我进阶中高级算法学习的第一步!
(虽然之前也搞过AC自动机、Tire数,但是效果不怎样,都是一两天就结束了,题目也没搞几个,就会简单应用,但是好像也足够了...)
我已经连续4、5天没有吃晚饭了,现在头有点昏昏的,不知道是不是饿了,反正脑子是一点都转不了,有时候还有点精神恍惚。。。
今天又是调了1天的dsu on tree的代码,过了两个题,但是搞懂了一点,这里先不写思路了,真的昏昏沉沉aaaa
CF1709
代码:
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define dwn(i,a,b) for(int i = a; i >= b; i--)
#define vi vector<int>
typedef long long ll;
const int N = 2e5+10;
int n, d[N], a[N], ans;
vector<int> g[N];
set<int> s[N]; //每棵树的前缀和集合
//找lca啊,路径权值抑或和
void dfs(int u, int fa){
s[u].insert(d[u]);
bool flg = 0;
for(auto v : g[u]){
if(v == fa) continue;
d[v] = d[u] ^ a[v];
dfs(v,u);
if(s[u].size() < s[v].size()) swap(s[u],s[v]);
for(auto x : s[v]){
if(s[u].find(x ^ a[u]) != s[u].end()) flg = 1;
}
for(auto x : s[v]) s[u].insert(x);
}
if(flg) ans++, s[u].clear();
}
void solve(){
cin >> n;
rep(i,1,n) cin >> a[i];
rep(i, 1, n-1){
int u, v; cin >> u >> v;
g[u].pb(v);
g[v].pb(u);
}
d[1] = a[1];
dfs(1,0);
cout << ans << '\n';
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//int _;cin>>_;while(_--)
solve();return 0;
}
CF600E
醉了,一个板子调了4h
代码:
// /*
// 询问子树信息:考虑dsu on tree
// 题意:a向下b层能不能构成回文串?
// 检查以a为根的子树,第b层颜色种类奇数个数 <= 1即可
// */
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
using ll = long long;
int n;
int g[MAXN],tot,dfn,u,v;
int sz[MAXN],deep[MAXN],fa[MAXN],son[MAXN],L[MAXN],R[MAXN],Index[MAXN],skp,col[MAXN],nowans,cnt[MAXN];
//图的存储
//int tot, g[MAXN];
struct edges
{
int to, nxt;
}e[2 * MAXN];
void add_edge(int from, int to){
e[++tot].to = to;
e[tot].nxt = g[from];
g[from] = tot;
}
//树剖 + 维护dfn序
//int sz[MAXN], deep[MAXN], son[MAXN], fa[MAXN], L[MAXN], R[MAXN], Index[MAXN];
void dfs(int x, int dep, int father){
sz[x] = 1, deep[MAXN] = dep, son[x] = 0, fa[x] = father;
L[x] = ++dfn, Index[dfn] = x;
for(int i = g[x]; i; i = e[i].nxt){
if(e[i].to == father)continue;
dfs(e[i].to, dep+1, x);
sz[x] += sz[e[i].to];
if(!son[x] || sz[son[x]] < sz[e[i].to]) son[x] = e[i].to;
}
R[x] = dfn;
}
//int skp, cnt[MAXN], col[MAXN], nowans, ans[MAXN];
// dsu:数据结构维护信息:每颗子树的颜色种类数,增加,删除
ll max_cnt, max_col, sum,ans[MAXN];
void get_data(int x){
for(int i = L[x]; i <= R[x]; i++){
if(Index[i] == skp){
i = R[Index[i]];
continue;
}
int c = col[Index[i]];
cnt[c]++;
if(cnt[c] > max_cnt){
max_cnt = cnt[c];
sum = c;
}else if(cnt[c] == max_cnt){
sum += c;
}
}
}
void del_data(int x){
for(int i = L[x]; i <= R[x]; i++){
if(skp == Index[i]) {
i = R[Index[i]];
continue;
}
cnt[col[Index[i]]]--;
}
}
void dsu(int x, bool tag){
for(int i = g[x]; i; i = e[i].nxt){
if(e[i].to == son[x] || e[i].to == fa[x]) continue;
dsu(e[i].to, 1);
}
if(son[x]){
dsu(son[x],0);
skp = son[x];
}
get_data(x); // 处理轻儿子
ans[x] = sum;
if(tag){ //轻儿子删除数据结构中的信息
skp = 0;
sum = max_cnt = 0;
del_data(x);
}
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%d", &col[i]);
}
for(int i = 1; i <= n-1; i++){
scanf("%d%d", &u, &v);
add_edge(u,v);
add_edge(v,u);
}
dfs(1,0,-1);
dsu(1,0);
for(int i = 1; i <= n; i++){
printf("%lld%c", ans[i], " \n"[i == n]);
}
return 0;
}
状态很差,希望我还能活到今晚22:35的edu场

浙公网安备 33010602011771号