[LNOI2014] LCA

news/2024/10/22 21:17:48

[LNOI2014] LCA

乐子

image

笑点解析:单log疯狂卡常才卡过那两双log做法。

全局平衡二叉树解法。

考虑差分,然后挂扫描线。\(dep_{LCA(x,y)}\)实际上就是将\(x\)到根的节点权值加1,然后求\(y\)到根的节点的权值和。

然后就是全局平衡二叉树的板子,标记永久化写就好了。

应该会抽时间写一个全局平衡二叉树的学习笔记,会把这道题当做例题,所以这里就不多说了。

点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define rep(i,s,t,p) for(register int i = s;i <= t; i += p)
#define drep(i,s,t,p) for(register int i = s;i >= t; i -= p)
namespace IO{#ifdef LOCALFILE*Fin(fopen("in.in","r")),*Fout(fopen("out.out","w"));#elseFILE*Fin(stdin),*Fout(stdout);#endifclass qistream{static const size_t SIZE=1<<27,BLOCK=64;FILE*fp;char buf[SIZE];int p;public:qistream(FILE*_fp=stdin):fp(_fp),p(0){fread_unlocked(buf+p,1,SIZE-p,fp);}void flush(){memmove(buf,buf+p,SIZE-p),fread_unlocked(buf+SIZE-p,1,p,fp),p=0;}qistream&operator>>(char&str){str=getch();while(isspace(str))str=getch();return*this;}template<class T>qistream&operator>>(T&x){x=0;p+BLOCK>=SIZE?flush():void();bool flag=false;for(;!isdigit(buf[p]);++p)flag=buf[p]=='-';for(;isdigit(buf[p]);++p)x=x*10+buf[p]-'0';x=flag?-x:x;return*this;}char getch(){return buf[p++];}qistream&operator>>(char*str){char ch=getch();while(ch<=' ')ch=getch();for(int i=0;ch>' ';++i,ch=getch())str[i]=ch;return*this;}}qcin(Fin);class qostream{static const size_t SIZE=1<<27,BLOCK=64;FILE*fp;char buf[SIZE];int p;public:qostream(FILE*_fp=stdout):fp(_fp),p(0){}~qostream(){fwrite_unlocked(buf,1,p,fp);}void flush(){fwrite_unlocked(buf,1,p,fp),p=0;}template<class T>qostream&operator<<(T x){int len=0;p+BLOCK>=SIZE?flush():void();x<0?(x=-x,buf[p++]='-'):0;do buf[p+len]=x%10+'0',x/=10,++len;while(x);for(int i=0,j=len-1;i<j;++i,--j)swap(buf[p+i],buf[p+j]);p+=len;return*this;}qostream&operator<<(char x){putch(x);return*this;}void putch(char ch){p+BLOCK>=SIZE?flush():void();buf[p++]=ch;}qostream&operator<<(char*str){for(int i=0;str[i];++i)putch(str[i]);return*this;}}qcout(Fout);
}using namespace IO;
#define rint register int
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
#define vec vector
#define eb emplace_back
#define N 50001
#define mod 201314
__int128_t base = 1;
template<class T>
inline T Mod(T x){return x-mod*(base*x>>64);}
vec<int> e[N];
int n,m,cq;
int siz[N],son[N],fa[N],c[N],sc[N],ss[N],lc[N],rc[N],ans[N];
int tag[N],sum[N];
struct node{int id,x,z;bool sgn;}q[N<<1];
void dfs1(rint x){siz[x] = 1;for(int y:e[x]){if(y == fa[x]) continue;fa[y] = x;dfs1(y);siz[x] += siz[y];if(!son[x] || siz[son[x]] < siz[y]) son[x] = y;}
}
int buildc(rint ql,rint qr){rint l = ql,r = qr,pos = 0,len = (sc[qr] - sc[ql]);while(l <= r){rint mid = (l + r) >> 1;if(2*(sc[mid]-sc[ql]) <= len) pos = mid,l = mid + 1;else r = mid - 1;}rint x = c[pos];ss[x] = qr-ql;if(ql < pos) fa[lc[x] = buildc(ql,pos)] = x;if(pos + 1 < qr) fa[rc[x] = buildc(pos+1,qr)] = x;return x;
}
int build(rint x){rint y = x;do for(int v:e[y]) if(v ^ son[y]) fa[build(v)] = y; while(y = son[y]);y = 0;do c[y++] = x,sc[y] = sc[y-1] + siz[x] - siz[son[x]];while(x = son[x]);return buildc(0,y);
}
inline void upd(rint x){bool flag = true;rint val = 0;while(x){sum[x] += val;if(flag){tag[x]++;if(rc[x]) tag[rc[x]]--;val += 1 + ss[lc[x]];sum[x] -= ss[rc[x]];}flag = (x ^ lc[fa[x]]);if(flag && (x ^ rc[fa[x]])) val = 0;x = fa[x];}
}
inline int qry(rint x){rint res = 0,val = 0;bool flag = true;while(x){if(flag){res += sum[x] - sum[rc[x]];res -= ss[rc[x]]*tag[rc[x]];val += 1 + ss[lc[x]];}res += val*tag[x];flag = (x ^ lc[fa[x]]);if(flag && (x ^ rc[fa[x]])) val = 0;x = fa[x];}return res;
}
inline void solve(){base = (base<<64)/mod;qcin>>n>>m;rint f,l,r,x;rep(i,2,n,1){qcin>>f;f++;e[f].eb(i);}rep(i,1,m,1){qcin>>l>>r>>x;r++;x++;if(l) q[++cq] = {i,l,x,0};q[++cq] = {i,r,x,1};}dfs1(1);rep(i,1,n,1) fa[i] = 0;build(1);int now = 0;sort(q+1,q+1+cq,[](node x,node y){return x.x<y.x;});rep(i,1,cq,1){while(now < q[i].x) now++,upd(now);if(q[i].sgn) ans[q[i].id] += qry(q[i].z);else ans[q[i].id] -= qry(q[i].z);}rep(i,1,m,1) qcout<<Mod(ans[i])<<'\n';}
signed main(){// cin.tie(nullptr)->sync_with_stdio(false);solve();
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

倍增st表

首先,因为士兵是环形的,所以先将其拆分为链,并且每个士兵的移动位子不会被包含,所以只需要对左端点进行排序就能得到一个递增的区间点击查看代码 void init() {cin >> n >> m;int i;for (i = 1; i <= n; ++i){w[i].i1 = i;cin >> w[i].l >> w[i…

前后端实现双Token无感刷新用户认证

前后端实现双Token无感刷新用户认证 本文记录了使用双Token机制实现用户认证的具体步骤,前端使用的Vue,后端使用SpringSecurity和JWT 双Token分别指的是AccessToken和RefreshToken AccessToken:每次请求需要携带AccessToken访问后端数据,有效期短,减少AccessToken泄露带来…

门罗币隐私保护之环签名

主页微信公众号:密码应用技术实战 博客园首页:https://www.cnblogs.com/informatics/ GIT地址:https://github.com/warm3snow简介 在《门罗币隐私保护之隐形地址》文章中,我们重点介绍了门罗币Monero的隐形地址技术,门罗币通过隐形地址保证了交易的不可链接性,并实现了用…

Maven的学习

Maven 安装与配置 今天我们来学习一下Maven,Maven就相当于一个管理的工具,原理就是使用一个插件,这个插件由多个jar包构成。 在一个公司的项目开发过程中,一个大的项目通常被分为好几个小的模块,由不同的人去完成,但是不同的人在开发的过程中,使用的组件,jar包难免会有…

jdk8中文文档及安卓阅读器

例:下载链接: 文档(密码:76nh) 软件(密码:5wrj) 原文链接: http://466dd.com

7-1计算阶乘和【PTA嵌套循环程序设计】

嵌套循环程序设计 7-1计算阶乘和#include<stdio.h>int f(int a){int sum = 1;for(int i=1;i<=a;i++){sum *= i;}return sum;}//构造N!函数int main(){int N = 0,sum = 0;//初始化scanf("%d",&N);if(N>1){for(int i=1;i<=N;i++){sum += f(i);//实…

从认识 Kubernetes 开始

你也说,我也说,那什么是 K8s 呢?Author: ACatSmiling Since: 2024-10-21认识 Kubernetes 什么是 Kubernetes 官方网站:https://kubernetes.io Kubernetes,是 Google 严格保密十几年的秘密武器 Borg 系统的一个开源版本,于 2014 年 9 月发布第一个版本,2015 年 7 月发布第…

java的三大程序结构

JAVA的三大程序结构 一:顺序结构 程序走上执行到下。 二:选择结构 if单选择结构 if(布尔表达式){ //如果布尔表达式的值为ture则执行{}里的语句块 } public class IfDemo01 {public static void main(String[] args) {//接收键盘输入Scanner scanner = new Scanner(System.…