给一棵树,维护上面两点最短路径中结点的最大值及最大值出现次数

#include <stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 300010+10;
#define inf 1000000005
typedef pair<int,int>pii;
int w[maxn];
int N, Q;struct
{int to,next,w;
}e[maxn<<2];int head[maxn<<1],edgeNum;struct
{int u,v;
}edge[maxn<<1];void add(int u,int v)
{e[edgeNum].next = head[u];e[edgeNum].to = v;// e[edgeNum].w=w;head[u] = edgeNum++;
}/*-------------------------树剖------------------------------*/
int deep[maxn],fa[maxn],siz[maxn],son[maxn];
void dfs1(int u,int pre,int d)
{deep[u] = d;fa[u] = pre;siz[u] = 1;son[u] = 0;for(int i=head[u];~i;i=e[i].next){int v = e[i].to;if(v!=pre){dfs1(v,u,d+1);siz[u] += siz[v];if(siz[v]>siz[son[u]])son[u] = v;}}
}int top[maxn],id[maxn],rk[maxn],cnt;void dfs2(int u,int t)
{top[u] = t;id[u] = ++cnt;rk[cnt] = u;if(!son[u]) return;dfs2(son[u],t);for(int i=head[u];~i;i=e[i].next){int v = e[i].to;if(v!=son[u]&&v!=fa[u])dfs2(v,v);}
}
/*-------------------------树剖------------------------------*//*-------------------------线段树------------------------------*/
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int sum[maxn<<2],maxv[maxn<<2],lazy[maxn<<2],ci[maxn<<2];
void pushup(int rt)
{if(maxv[rt<<1]>maxv[rt<<1|1]){sum[rt]=sum[rt<<1];}else if(maxv[rt<<1]<maxv[rt<<1|1])sum[rt]=sum[rt<<1|1];else sum[rt] = (sum[rt<<1] + sum[rt<<1|1]);maxv[rt] =max(maxv[rt<<1],maxv[rt<<1|1]);
}void change(int val,int q,int l,int r,int rt)//单点更新
{if(l==r){sum[rt]=1;//出现次数 maxv[rt]=val;return ;}int m = l + r >> 1;if(q<=m)change(val,q,lson);elsechange(val,q,rson);pushup(rt);
}pii query(int L,int R,int l,int r,int rt)
{if(L<=l&&r<=R)return {maxv[rt],sum[rt]};int m = l + r >> 1;pii a={0,0},b={0,0},ans;if (L<=m)a=query(L,R,lson);if (R>m)b=query(L,R,rson);if(a.first==b.first)ans={a.first,a.second+b.second};else if(a.first<b.first)ans=b;else ans=a;return ans;
}int querymax(int L,int R,int l,int r,int rt){if (L<=l&&r<=R)return maxv[rt];int m=(l+r)>>1,ans=-inf;//注意负数① if (L<=m)ans=max(ans,querymax(L,R,lson));if (R>m)ans=max(ans,querymax(L,R,rson));//pushup(rt);return ans;
}
/*-------------------------线段树------------------------------*//*-----------------------树剖加线段树--------------------------*/pii query(int x,int y)
{pii ans = {-2,-2};while(top[x] != top[y]){if(deep[top[x]] < deep[top[y]])swap(x,y);pii tmp = query(id[top[x]],id[x],1,cnt,1); if(tmp.first==ans.first)ans={tmp.first,tmp.second+ans.second};else if(tmp.first>ans.first)ans=tmp;x = fa[top[x]];}if(deep[x]>deep[y])swap(x,y);pii tmp = query(id[x],id[y],1,cnt,1); if(tmp.first==ans.first)ans={tmp.first,tmp.second+ans.second};else if(tmp.first>ans.first)ans=tmp;return ans;
}int querymax(int x,int y)
{int ans =-inf;//注意负数② while(top[x] != top[y]){if(deep[top[x]] < deep[top[y]])swap(x,y);ans = max(ans ,querymax(id[top[x]],id[x],1,cnt,1)); x = fa[top[x]];}if(deep[x]>deep[y])swap(x,y);ans = max(ans ,querymax(id[x],id[y],1,cnt,1));return ans;
}
/*-----------------------树剖加线段树--------------------------*/void init()
{memset(head,-1,4*N+4);cnt = edgeNum = 0;
}int u, v, o,z,cur;
int main()
{   scanf("%d",&N);init();for(int i=1;i<=N;i++)scanf("%d",&w[i]);for(int i=1;i<N;++i){//w[i] = 0;scanf("%d%d",&u,&v);
//      edge[i].u=u,edge[i].v=v;//真正的边数 add(u,v);//边数*2 add(v,u);}dfs1(1,0,1);dfs2(1,1);for(int i=1;i<=N;i++){change(w[i],id[i],1,N,1);}scanf("%d",&Q);
//  build(1,cnt,1);while(Q--){scanf("%d%d",&o,&z);pii res=query(o,z);printf("%d %d\n",res.first,res.second);}return 0;
}

感谢睿明锅,lca做法待更

个人赛C 柠檬树2--树链剖分+维护最值出现次数/LCA相关推荐

  1. 树链剖分+线段树 HDOJ 4897 Little Devil I(小恶魔)

    题目链接 题意: 给定一棵树,每条边有黑白两种颜色,初始都是白色,现在有三种操作: 1 u v:u到v路径(最短)上的边都取成相反的颜色 2 u v:u到v路径上相邻的边都取成相反的颜色(相邻即仅有一 ...

  2. AcWing 397. 逃不掉的路(边双连通分量缩点成树 + 树链剖分乱搞)

    整理的算法模板合集: ACM模板 我们知道在同一个边双连通分量中的点没有必经边(因为至少有两条分离的路径). 所以我们直接tarjan求出桥后缩点,然后求一下树上两点间的距离即可. 那么如何求树上两点 ...

  3. [ZJOI2015] 幻想乡战略游戏(树链剖分 + 线段树二分 + 带权重心)

    problem luogu-P3345 solution 这是一个带权重心的题,考察动态点分治.点分治?呵,不可能的,这辈子都不可能写点分治 我们重新考虑重心的性质:以这个点为根时,所有子树的大小不会 ...

  4. [NOI2021 day1]轻重边(树链剖分),路径交点(矩阵行列式)

    NOI 2021 day1 轻重边 description solution code 路径交点 description solution code 轻重边 description solution ...

  5. YbtOJ-交换游戏【树链剖分,线段树合并】

    正题 题目大意 给出两棵树,对于第一棵树的每一条边(x,y)(x,y)(x,y)询问有多少条在第二棵树上的边(u,v)(u,v)(u,v)与其交换(连接的序号相同)后两棵树依旧是一棵树. 1≤n≤2× ...

  6. P6805-[CEOI2020]春季大扫除【贪心,树链剖分,线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/P6805 题目大意 给出nnn个点的一棵树,qqq次独立的询问.每次询问会在一些节点上新增一些子节点,然后你每次可以 ...

  7. jzoj3626-[LNOI2014]LCA【树链剖分,线段树】

    正题 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3626 题目大意 一棵树,每次给出(l,r,z)(l,r,z)(l,r,z)询问∑i ...

  8. BZOJ 2243 染色(树链剖分好题)

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 7971  Solved: 2990 [Submit][Stat ...

  9. 洛谷P4482 [BJWC2018]Border 的四种求法 字符串,SAM,线段树合并,线段树,树链剖分,DSU on Tree...

    原文链接https://www.cnblogs.com/zhouzhendong/p/LuoguP4482.html 题意 给定一个字符串 S,有 q 次询问,每次给定两个数 L,R ,求 S[L.. ...

最新文章

  1. 入门4:PHP 语法基础1
  2. 深度学习笔记三:Softmax Regression
  3. 实操将TensorFlow模型部署成Docker服务化
  4. Java、Apache Tomcat下载与安装及环境变量配置
  5. 事务隔离级别(IsolationLevel)
  6. 零基础想学Python,明白这2点,越快年薪30W
  7. 计算机网络学习笔记--网络层知识点整理
  8. 信息系统监理师考试知识点整理
  9. html设置浮动框架的位置,网页浮动窗口怎么设置 怎么让链接网页在浮动框架中显示...
  10. PHP上传Excel文件
  11. http91spwp index.php,index.php
  12. 三菱FX系列PLC以太网连接西门子wincc软件
  13. 英语口语测试对话软件,英语口语人机对话软件
  14. 分布式任务调度系列 - PowerJob
  15. python软件是干嘛的-Python到底能做什么?
  16. Flex布局及在移动端的应用
  17. web前端学习中CSS,JS代码压缩
  18. 3DS MAX插件制作绚丽的拖光效果-3D建模教程
  19. Python安装常见问题处理
  20. Python写一个递归函数

热门文章

  1. 计算机系统大作业:程序人生-Hello‘s P2P
  2. 小程序-文字超出限制
  3. 洛谷 P1618 三连击(升级版)
  4. Android 底层知识拾零
  5. 解决react脚手架运行后多出来很多webpack的日志
  6. 弱网络模拟测试工具---易测app
  7. 湖南某科技大学 安卓Android移动开发基础期中考试笔记(持续更新)
  8. Arthas在线诊断工具使用
  9. 计算机系统基础栈帧,2020春-计算机系统基础(一)-中国大学mooc-题库零氪
  10. 传统特征点检测器的检测特征点和匹配流程