当前位置: 首页 > 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.hskmm.com/?act=detail&tid=34537

相关文章:

  • 塔吊施工人员操作合规性监测!思通数科 AI 卫士实时守护作业安全
  • Dos命令1
  • 题解:P1073 [NOIP 2009 提高组] 最优贸易
  • 吩咐
  • 互评五
  • 机器人技术新前沿:自动驾驶路径规划算法解析
  • 前端框架文档新思路:基于源码解析的自动化方案
  • 常用模板
  • C++ std::forwardT 的使用
  • tryhackme-预安全-网络基础知识-数据包和帧-07
  • 迈向零信任存储:基于RustFS构建内生安全的数据架构
  • 如果这就是人类脑海的话 雪白纸上划出血红层层痕迹 不如杀死这些记忆
  • 嗣澳——扫,墨依奥——描,希伊桉——线
  • 服务器被攻击!原因竟然是他?真没想到...
  • 得到的眼泪学会了哭泣 得到的悲伤缓慢摧残肉体 被所爱之人踩在地
  • 框架架构的多维赋能——论其对自然语言处理深层语义分析的影响与启示
  • 使用 robocopy 命令备份还原数据速度统计
  • 顺天地之自然
  • Mac 打开终端方式
  • PWN手的成长之路-20-cgpwn2
  • 树状数组和线段树基础
  • C++ofstream写文件bug
  • Debian13中使用Virtual-box安装Window10虚拟机并设置USB直通
  • 2024长城杯决赛-溯源取证1
  • [Agent] ACE(Agentic Context Engineering)和Dynamic Cheatsheet学习笔记
  • 2025年9月模拟赛整合
  • 软工问题总结10.19
  • AI元人文构想研究:理论溯源、跨学科审视与技术路径探析
  • NOAI官方学术支持
  • 【ARM CoreLink 系列 4.1 -- NI-700 interconnect hub 控制器详细介绍】