当前位置: 首页 > news >正文

赛前训练 12 extra 树上差分倍增

A

树上差分板子.

B

每个点只有一条出边的有向图可以看作树

基于上述结论,我们直接倍增维护 \(\min,\operatorname{sum}\) 即可.

实现
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define int long long
using namespace std;const int N=1e5+5,M=48;
int n,k;
vector<int> G[N];
int dp[N][M],mn[N][M],sum[N][M];void solve(int x){int m=k,cur=x,ansmn=1e18,anss=0;for(int j=34;j>=0;j--){if((1ll<<j)<=m){ansmn=min(ansmn,mn[cur][j]);anss+=sum[cur][j];cur=dp[cur][j];m-=(1ll<<j);}}cout<<anss<<' '<<ansmn<<'\n';
}signed main(){ios::sync_with_stdio(0);cin.tie(0);cin>>n>>k;memset(mn,0x3f,sizeof mn);for(int i=1,u;i<=n;i++){cin>>u,u++;dp[i][0]=u;}for(int i=1,w;i<=n;i++){cin>>w;mn[i][0]=sum[i][0]=w;}for(int j=1;j<=34;j++){for(int i=1;i<=n;i++){dp[i][j]=dp[dp[i][j-1]][j-1];mn[i][j]=min(mn[i][j-1],mn[dp[i][j-1]][j-1]);sum[i][j]=sum[i][j-1]+sum[dp[i][j-1]][j-1];}}for(int i=1;i<=n;i++)solve(i);return 0;
}

C

容易发现每个点前面第一个和它不互质的数组成的子串必须得分成一段,这个很显然可以双指针维护.

然后对于区间 \([l,r]\),我们可以暴力跳出有多少个区间,但这样是 \(\mathcal{O}(n)\) 的,考虑倍增加速即可.

实现
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define int long long
using namespace std;const int N=1e5+5,V=1e5,M=48;
int n,tot,q;
int a[N],p[N],st[N][M];
bool vis[N],ok[N];
vector<int> s[N];void shai(){for(int i=2;i<=V;i++){if(!vis[i]){p[++tot]=i;for(int j=i*2;j<=V;j+=i)vis[j]=1;}}for(int i=1;i<=tot;i++)for(int j=p[i];j<=V;j+=p[i])s[j].emplace_back(i);
}
int qry(int l,int r){int res=0;for(int j=34;j>=0;j--){if(st[l][j]<=r){l=st[l][j];res+=(1ll<<j);}}res++;return res;
}
bool add(int x){for(int i:s[x])if(ok[i])return 0;for(int i:s[x])ok[i]=1;return 1;
}
void del(int x){if(!x)return;for(int i:s[x])ok[i]=0;
}signed main(){ios::sync_with_stdio(0);cin.tie(0);cin>>n>>q;for(int i=1;i<=n;i++)cin>>a[i];shai();for(int i=1,j=0;i<=n;i++){del(a[i-1]);while(j<n&&add(a[j+1]))j++;st[i][0]=j+1;}st[n+1][0]=n+1;for(int j=1;j<=34;j++){st[n+1][j]=n+1;for(int i=1;i<=n;i++)st[i][j]=st[st[i][j-1]][j-1];}while(q--){int l,r;cin>>l>>r;cout<<qry(l,r)<<'\n';}return 0;
}

D

对于一个节点,考虑其子树内和子树外的情形.

如果子树内有和当前节点相同的种类,则子树外的全部都得 ban,那个节点的兄弟们也得 ban,只有它自己子树内的不用 ban.

子树外的呢?画个图可以知道,只有那个子树外的节点到当前节点路径上中间的要 ban,结合上一种情形,我们发现只需要把当前节点的子树 ban 掉即可.

上述操作可以把树拍成序列后完成,搞完后做一遍前缀和即可.

实现
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define int long long
using namespace std;const int N=2e5+5;
int n,ans,all;
int a[N],b[N],siz[N],cnt[N],tot[N],dfn[N],out[N],d[N],s[N];
vector<int> G[N];void dfs(int cur,int fa){siz[cur]=1;dfn[cur]=++all;int pre=cnt[a[cur]];cnt[a[cur]]++;for(int i:G[cur]){if(i==fa)continue;int tmp=cnt[a[cur]];dfs(i,cur);siz[cur]+=siz[i];if(tmp!=cnt[a[cur]]){d[1]++;d[dfn[i]]--;d[out[i]+1]++;}}out[cur]=all;if(cnt[a[cur]]-pre<tot[a[cur]]){d[dfn[cur]]++;d[out[cur]+1]--;}
}signed main(){ios::sync_with_stdio(0);cin.tie(0);cin>>n;for(int i=1;i<=n;i++)cin>>a[i],b[i]=a[i];sort(b+1,b+n+1);int len=unique(b+1,b+n+1)-b-1;for(int i=1;i<=n;i++){a[i]=lower_bound(b+1,b+len+1,a[i])-b;tot[a[i]]++;}for(int i=1,u,v;i<n;i++){cin>>u>>v;G[u].push_back(v);G[v].push_back(u);}dfs(1,0);int ans=0;for(int i=1;i<=n;i++){s[i]=s[i-1]+d[i];if(!s[i])ans++;}cout<<ans;return 0;
}

总结

  • 两个小技巧:

    双指针:维护子串信息

    倍增:加速跳跃过程

  • 树上问题:

    与图的转化(单出边有向图)

    与序列的转化(dfn 序)

    画图、考虑子树外和子树内

以上.

http://www.jsqmd.com/news/16918/

相关文章:

  • 塔吊施工人员操作合规性监测!思通数科 AI 卫士实时守护作业安全
  • Dos命令1
  • 题解:P1073 [NOIP 2009 提高组] 最优贸易
  • 吩咐
  • 互评五
  • 机器人技术新前沿:自动驾驶路径规划算法解析
  • 前端框架文档新思路:基于源码解析的自动化方案
  • tryhackme-预安全-网络基础知识-数据包和帧-07
  • Agilent E363x 系列
  • 嗣澳——扫,墨依奥——描,希伊桉——线
  • 迈向零信任存储:基于RustFS构建内生安全的数据架构
  • 如果这就是人类脑海的话 雪白纸上划出血红层层痕迹 不如杀死这些记忆
  • 服务器被攻击!原因竟然是他?真没想到...
  • ChatGPT From Zero To Hero - LLM学习笔记(一) - 详解
  • 基于Java+SSM+Django数字工坊课程教学网站(源码+LW+调试文档+讲解等)/数字工坊/课程教学/网站链接/在线课程/学习资源/视频教程/教育平台/数字艺术/学习网站/课程资料/ - 详解
  • 框架架构的多维赋能——论其对自然语言处理深层语义分析的影响与启示
  • 路径规划算法学习Day1:深度优先搜索算法(DFS)
  • 深入理解 Java和Go语法和使用场景(指南十一) - 指南
  • .seq 是 TestStand Sequence File(测试序列文件) 的扩展名。
  • 使用 robocopy 命令备份还原数据速度统计
  • 顺天地之自然
  • 第2章 人工智能项目的核心特征与挑战
  • 深入解析:【办公类-115-04】20250920职称资料上传03——压缩课题结题报告PDF的大小(控制在200MB以内)
  • Mac 打开终端方式
  • 《青云志》
  • 树状数组和线段树基础
  • 详细介绍:Vue Router路由
  • AVR 单片机批量编程脚本(.bat)
  • PWN手的成长之路-20-cgpwn2
  • C++ofstream写文件bug