P3899 [湖南集训]更为厉害(线段树合并、长链剖分、二维数点)

P3899 [湖南集训]更为厉害

  • deepb<deepa\text{deep}_b<\text{deep}_adeepb<deepa:c 在点 a 的子树中,根据乘法原理计算答案为 min⁡(deepa,k)∗(sza−1)\min(\text{deep}_a,k)∗(\text{sz}_a−1)min(deepa,k)(sza1)
  • deepb>deepa\text{deep}_b>\text{deep}_adeepb>deepa:c 在点 b 的子树中,所以此时每个点 b 的贡献为 szb−1\text{sz}_b−1szb1

对于上述条件,满足深度限制即可。

Code1

线段树合并暴力合并子树

1.80s / 90.65MB / 1.82KB C++17

#include<bits/stdc++.h>using namespace std;
using ll=long long;
constexpr int N=300010;
int h[N],e[2*N],ne[2*N],idx;
void add(int a,int b){e[idx]=b,ne[idx]=h[a],h[a]=idx++;}
int n,q;
struct node
{int l,r;ll v;
}tree[N*40];
int root[N],cnt;
void insert(int &u,int l,int r,int pos,ll v)
{if(!u) u=++cnt;if(l==r) return tree[u].v+=v,void();int mid=l+r>>1;if(pos<=mid) insert(tree[u].l,l,mid,pos,v);elseinsert(tree[u].r,mid+1,r,pos,v);tree[u].v=tree[tree[u].l].v+tree[tree[u].r].v;
}
ll query(int u,int l,int r,int L,int R)
{if(!u) return 0ll;if(L<=l&&r<=R) return tree[u].v;int mid=l+r>>1;ll v=0;if(L<=mid)v+=query(tree[u].l,l,mid,L,R);if(R>mid)v+=query(tree[u].r,mid+1,r,L,R);return v;
}
int merge(int x,int y)
{if(!x||!y) return x+y;int u=++cnt;tree[u].v=tree[x].v+tree[y].v;tree[u].l=merge(tree[x].l,tree[y].l);tree[u].r=merge(tree[x].r,tree[y].r);return u;
}int dep[N],sz[N];void dfs(int u,int fa)
{dep[u]=dep[fa]+1;sz[u]=1;for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(v==fa) continue;dfs(v,u);sz[u]+=sz[v];root[u]=merge(root[u],root[v]);}insert(root[u],1,n,dep[u],sz[u]-1);
}int main()
{ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);cin>>n>>q;memset(h,-1,sizeof h);for(int i=1;i<n;i++){int u,v;cin>>u>>v;add(u,v),add(v,u);}dfs(1,0);while(q--){int p,k;cin>>p>>k;ll ans=0;ans+=1ll*min(k,dep[p]-1)*(sz[p]-1);ans+=query(root[p],1,n,dep[p]+1,dep[p]+k);cout<<ans<<'\n';}return 0;
}

Code2

长链剖分

1.51s / 48.94MB / 1.60KB C++17

#include<bits/stdc++.h>using namespace std;
using ll=long long;
constexpr int N=300010;
int h[N],e[2*N],ne[2*N],idx;
void add(int a,int b){e[idx]=b,ne[idx]=h[a],h[a]=idx++;}
ll ans[N];
int n,m;
int ht[N],son[N],sz[N],dep[N];
void dfs1(int u,int fa)
{sz[u]=1;dep[u]=dep[fa]+1;for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(v==fa) continue;dfs1(v,u);sz[u]+=sz[v];if(ht[son[u]]<ht[v]) son[u]=v;}ht[u]=ht[son[u]]+1;
}
ll pool[N];
ll *f[N],*now=pool;
ll tag[N];
vector<pair<int,int>> q[N];
void dfs2(int u,int fa)
{if(son[u]){f[son[u]]=f[u]+1;dfs2(son[u],u);tag[u]=tag[son[u]]+sz[son[u]]-1;}for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(v==fa||v==son[u]) continue;f[v]=now;now+=ht[v];dfs2(v,u);tag[u]+=tag[v]+sz[v]-1;for(int j=1;j<ht[v];j++)f[u][j]+=f[v][j-1];//+tag[v]+sz[v]-1;}f[u][0]-=tag[u];for(auto [k,id]:q[u]) ans[id]=1ll*min(dep[u]-1,k)*(sz[u]-1)+f[u][min(k,ht[u]-1)]+tag[u];
}int main()
{ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);cin>>n>>m;memset(h,-1,sizeof h);for(int i=1;i<n;i++){int u,v;cin>>u>>v;add(u,v),add(v,u);}for(int i=1;i<=m;i++){int p,k;cin>>p>>k;q[p].push_back({k,i});}dfs1(1,0);f[1]=now;now+=ht[1];dfs2(1,0);for(int i=1;i<=m;i++) cout<<ans[i]<<'\n';return 0;
}

Code3

主席树二维数点

2.58s / 107.27MB / 1.85KB C++17

#include<bits/stdc++.h>using namespace std;
using ll=long long;
constexpr int N=300010;
int h[N],e[2*N],ne[2*N],idx;
void add(int a,int b){e[idx]=b,ne[idx]=h[a],h[a]=idx++;}
int n,q;
struct node
{int l,r;ll v;
}tree[N*40];
int rt[N],cnt;
void insert(int &u,int o,int l,int r,int pos,ll v)
{tree[u=++cnt]=tree[o];tree[u].v+=v;if(l==r) return;int mid=l+r>>1;if(pos<=mid) insert(tree[u].l,tree[o].l,l,mid,pos,v);elseinsert(tree[u].r,tree[o].r,mid+1,r,pos,v);
}
ll query(int u,int l,int r,int L,int R)
{if(!u) return 0ll;if(L<=l&&r<=R) return tree[u].v;int mid=l+r>>1;ll v=0;if(L<=mid)v+=query(tree[u].l,l,mid,L,R);if(R>mid)v+=query(tree[u].r,mid+1,r,L,R);return v;
}int dep[N],sz[N];
int L[N],timestamp,R[N];void dfs1(int u,int fa)
{L[u]=++timestamp;dep[u]=dep[fa]+1;sz[u]=1;for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(v==fa) continue;dfs1(v,u);sz[u]+=sz[v];}R[u]=timestamp;}
void dfs2(int u,int fa)
{insert(rt[L[u]],rt[L[u]-1],1,n,dep[u],sz[u]-1);for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(v==fa) continue;dfs2(v,u);}
}
int main()
{ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);cin>>n>>q;memset(h,-1,sizeof h);for(int i=1;i<n;i++){int u,v;cin>>u>>v;add(u,v),add(v,u);}dfs1(1,0);dfs2(1,0);while(q--){int u,k;cin>>u>>k;ll ans=0;ans+=1ll*min(k,dep[u]-1)*(sz[u]-1);ans+=query(rt[R[u]],1,n,dep[u]+1,dep[u]+k)-query(rt[L[u]-1],1,n,dep[u]+1,dep[u]+k);cout<<ans<<'\n';}return 0;
}

本质上线段树合并是通过该节点的子树构建当前树直接得到子树信息,而主席树是通过转化dfs序构建前缀树,通过作差得到子树的信息。

如果某些信息不支持做差得到,那么主席树的做法将失效,而线段树合并仍然适用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/318576.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

树链剖分-学习报告

概要 &#xff08;这是笔者刚学完趁热写的博客 由于也是初学&#xff0c;所以可能会对初学读者比较友好吧 毕竟你不明白的地方我可能也迷惑过&#xff09; 学完感觉树链剖分的设计真的很巧妙 其主要用途是压缩树上路径 又是一个n到log的优化 原理 先引定义&#xff1a; 设…

牛客题霸 [拼接所有的字符串产生字典序最小的字符串] C++题解/答案

牛客题霸 [拼接所有的字符串产生字典序最小的字符串] C题解/答案 题目描述 给定一个字符串的数组strs&#xff0c;请找到一种拼接顺序&#xff0c;使得所有的字符串拼接起来组成的字符串是所有可能性中字典序最小的&#xff0c;并返回这个字符串。 题解&#xff1a; 用sort…

今日头条Marketing API小工具(.Net Core版本)

前言由于工作原因&#xff0c;需要用到今日头条的Marketing API做一些广告投放的定制化开发。然后看现在网上也没多少关于头条Marketing API的文章&#xff0c;于是便就有了该篇文章。头条Marketing API主页地址&#xff1a;https://ad.toutiao.com/openapi/index.html。头条Ma…

P6880-[JOI 2020 Final]オリンピックバス【最短路】

正题 题目链接:https://www.luogu.com.cn/problem/P6880 题目大意 给出nnn个点mmm条边的有向图&#xff0c;边有边权和一个翻转权值。 翻转至多一条边使得1−>n−>11->n->11−>n−>1往返的权值加上翻转权值最小。 1≤n≤200,1≤m≤51041\leq n\leq 200,1\…

The 2020 ICPC Asia Macau Regional Contest J. Jewel Grab(数颜色+链表)

J. Jewel Grab Tartarus _Wallace_ 转化询问&#xff1a;对于一个询问 [s,k]&#xff0c;找到一个最长的区间 [s,t]&#xff0c;满足区间中出现次数超过一次的元素&#xff0c;的出现次数减一&#xff0c;的和&#xff0c;不超过 k。 对于该区间[s,t] 区间数颜色&#xff1a;…

牛客题霸 [最大数] C++题解/答案

牛客题霸 [最大数] C题解/答案 题目描述 给定一个数组由一些非负整数组成&#xff0c;现需要将他们进行排列并拼接&#xff0c;使得最后的结果最大&#xff0c;返回值需要是string类型 否则可能会溢出 题解&#xff1a; 将字符串存入vector中然后sort排序&#xff0c;最后将…

模板:割点、桥与双连通

文章目录割点代码桥点双连通分量代码边双连通分量代码割点 和强连通分量十分相似 分为树枝边、前向边和后向边 注意&#xff01; if(x!r&&low[to]>dfn[x]) cut[x]1;这句判断只能在树枝边出现 否则会因为前向边的存在而出错 代码 #include<bits/stdc.h> us…

.NET Core实战项目之CMS 第十章 设计篇-系统开发框架设计

这两天比较忙&#xff0c;周末也在加班&#xff0c;所以更新的就慢了一点&#xff0c;不过没关系&#xff0c;今天我们就进行千呼万唤的系统开发框架的设计。不知道上篇关于架构设计的文章大家有没有阅读&#xff0c;如果阅读后相信一定对架构设计有了更近一部的理解&#xff0…

喝酒、工作与自律

喝酒 自从开始打算品酒之后&#xff0c;家里的小酒数量不断增加&#xff0c;每天晚上喝个15ml&#xff0c;慢慢也能喝出一些区别了。 酱香、清香、浓香的区别还是挺明显的&#xff0c;闻香就能区别出来 浓香里的五粮液特点很明显&#xff0c;闻的时候有粮香&#xff0c;入口后…

51nod1836-战忽局的手段【期望dp,矩阵乘法】

正题 题目连接:http://www.51nod.com/Challenge/Problem.html#problemId1836 题目大意 nnn个点mmm次随机选择一个点标记&#xff08;可以重复&#xff09;&#xff0c;求最后被标记点的期望个数。 1≤n,m≤10181\leq n,m\leq 10^{18}1≤n,m≤1018 解题思路 额开始拿方案数推了…

分析现有 WPF / Windows Forms 程序能否顺利迁移到 .NET Core 3.0

今年五月的 Build 大会上&#xff0c;微软说 .NET Core 3.0 将带来 WPF / Windows Forms 这些桌面应用的支持。当然&#xff0c;是通过 Windows 兼容包&#xff08;Windows Compatibility Pack&#xff09;实现的。为了提前检查你的程序是否能在未来跑在 .NET Core 3.0 上&…

第 45 届国际大学生程序设计竞赛(ICPC)亚洲区域赛(昆明) Stone Games

Stone Games 主席树 Code1 #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N1000010; using lllong long; const ll MAX1000000000ll; int n,a[N],m; struct node {int l,r;ll v; }tree[N*40]; int root[N],c…

路径求和(ybtoj-树形dp)

文章目录题目描述解析代码题目描述 给出一棵带边权的树&#xff0c;求所有至少有一个端点为叶节点的所有简单路径的长度和 解析 换一个角度想 考虑将树分割为AB两部分的一条边会存在于多少条符合条件的路径中&#xff08;也就是边权会考虑多少次&#xff09; 不难发现&#…

51nod1675-序列变换【莫比乌斯反演】

正题 题目连接:http://www.51nod.com/Challenge/Problem.html#problemId1675 题目大意 给出两个长度为nnn的序列a,ba,ba,b&#xff0c;求有多少对x,yx,yx,y满足 gcd(x,y)1且abxbaygcd(x,y)1且a_{b_x}b_{a_y}gcd(x,y)1且abx​​bay​​ 1≤n≤105,1≤ai,bi≤n1\leq n\leq 10^5…

牛客题霸 [子数组最大乘积] C++题解/答案

牛客题霸 [子数组最大乘积] C题解/答案 题目描述 给定一个double类型的数组arr&#xff0c;其中的元素可正可负可0&#xff0c;返回子数组累乘的最大乘积。 题解&#xff1a; 同时记录最大值和最小值&#xff0c;为什么?因为给的元素是存在负数的&#xff0c;当出现负数时…

ML.NET 0.8特性简介

本周.NET生态圈内的更新源源不断&#xff0c;除了.NET Core 2.2&#xff0c;ASP.NET Core 2.2和Entity Framework Core 2.2之外&#xff0c;ML.NET 0.8也一并登上舞台。新的推荐场景ML.NET使用基于矩阵分解(Matrix Factorization)和场感知分解机(Field-aware Factorization Mac…

F-Lucky Pascal Triangle(Lucas+数位dp)

F-Lucky Pascal Triangle issue是fw题解 下面代码TLE了&#xff0c;但是此题数位dp的思想非常值得学习 Lucas的过程相当于把n,mn,mn,m在p进制下的每一位拿出来做组合数 Lucas(n,m,p)∏(nkmk)modp\text{Lucas}(n,m,p)\prod \dbinom {n_k}{m_k} \bmod pLucas(n,m,p)∏(mk​nk​…

树的合并(ybtoj-树上dp)

文章目录题目描述前言解析代码thanks for reading&#xff01;题目描述 前言 全网唯一AC&#xff01;&#xff01;&#xff01; 妙啊 而且还是完全自己想出来的做法 开心 &#xff08;APIO还是没白听&#xff09; 但是思路出来后代码实现十分坎坷 建两个图分别dfs3次那个地方…

牛客题霸 [矩阵元素查找] C++题解/答案

牛客题霸 [矩阵元素查找] C题解/答案 题目描述 已知int一个有序矩阵mat&#xff0c;同时给定矩阵的大小n和m以及需要查找的元素x&#xff0c;且矩阵的行和列都是从小到大有序的。设计查找算法返回所查找元素的二元数组&#xff0c;代表该元素的行号和列号(均从零开始)。保证元…

51nod1821-最优集合【贪心】

正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId1821 题目大意 nnn个可重集合&#xff0c;TTT次询问&#xff0c;询问将集合SxS_xSx​和一个选出大小为kkk的SyS_ySy​的子集合并成的独立集S′SS′满足能够找到一个最大的zzz使得对于任意的正整数i∈[1,z…