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

#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. 【算法】快速排序算法的编码和优化
  2. Bookshelf 2
  3. [html] 为什么我们要使用web workers?
  4. Python机器学习:KNN算法之01KKN基础
  5. Pandas 文本数据方法 findall( )
  6. 批处理写的关机小程序--bat
  7. 【NDSS 2021】On the Insecurity of SMS One-Time Password Messages against Local Attackers 论文笔记
  8. wgs84坐标系经纬度投影_南方cass坐标转经纬度_坐标转经纬度软件
  9. st58服务器装系统,安装系统 - 微擎 - 公众平台自助开源引擎
  10. vue 电视看板_基于Vue的拖放看板
  11. 小学计算机教师业务笔记,小学教师业务笔记
  12. 三菱Fx系列PLC的编程口协议
  13. python求助神器_【python从零开始(被称之为神器的装饰器)】- 环球网校
  14. 女生突然不回微信,那你首先得明白不回微信的原因
  15. Android wifi密码 源码,Android 修改WiFi热点的默认SSID和密码
  16. android释放内存只有1GB,手机内存不够用?教你5秒删掉1G垃圾,提升速度!
  17. VIP网易邮箱,163VIP邮箱,新浪vip等邮箱的对比分析
  18. 让爱永不过期,三公仔给你“旧药换新”
  19. java环境变量含义_java环境变量的配置及各环境变量的含义
  20. 如何查看exe或dll的依赖库dll

热门文章

  1. 虹科分享 | 终端安全防护 | 网络安全术语列表(终篇)
  2. 在那江南烈日与阵雨中-江南100赛记
  3. 吴恩达机器学习CS229A_EX2_逻辑回归与正则化_Python3
  4. 《航空系统》项目研发总结
  5. Linux/centOS安装lftp
  6. mysql中根据部门名称生成部门简称(根据某一列的关键字在另一列生成特定值)
  7. matlab susan,SUSAN算法的matlab代码
  8. 操作系统之进程的同步机制
  9. web前端开发自学难吗,前端开发网上学习
  10. buctoj-寒假集训进阶训练赛(二十二)