可持久化数据结构(平衡树、trie树、线段树) 总结
然而好像没有平衡树
还是题解包:
T1:森林
树上主席树+启发式合并。
然而好像知道标签就没啥了。在启发式合并时可以顺手求lca
然而这题好像可以时间换空间(回收空间)

T2:影魔
难点在于考虑贡献的来源
考虑一个区间两端点和区间最值(不含端点)的关系
小,中,大:贡献p1
大,小,大:贡献p2
大,中,小:贡献p1
则预处理出每个点左右第一个比它大的数的位置,设为l和r
则l会对r有p2的贡献,l会对i+1~r-1产生p1的贡献,同理r会对l+1~i-1产生p1的贡献。
用线段树维护扫描线,正向,逆向分别扫一遍,先把贡献都加进线段树,扫到某个点时先统计贡献再在线段树中减掉贡献。
具体实现见代码
T3:世博会
其实难点在于将切比雪夫距离转化为曼哈顿距离,然后主席树维护即可,将两维分开考虑,分别取中位数即可。
T4:Obserbing the tree树上询问
可持久化线段树+标记永久化。在线段树的每个节点维护等差数列的首项和公比,利用标记永久化减少节点数量
新建一个状态类似于主席树的建树,用树剖维护即可(线段树也是按dfs序建的)
#include<bits/stdc++.h>
#define N 200050
#define LL long long
#define int long long
using namespace std; int he[N],ne[N<<],to[N<<],cnt;
inline void addedge(int x,int y){
to[++cnt]=y;ne[cnt]=he[x];he[x]=cnt;
} int n,m;
int rt[N];
int lc[N*],rc[N*],tot;
LL sum[N*],d[N*],s[N*];
inline LL cal(int a,int d,LL n){
return a*n+d*(n-)*n/;
}
inline void upd(int g,int n){
sum[g]=sum[lc[g]]+sum[rc[g]]+cal(s[g],d[g],n);
}
int merge(int x,int y,int l,int r){
if(!x||!y)return x|y;
s[x]+=s[y];d[x]+=d[y];
if(l^r){
const int m=l+r>>;
lc[x]=merge(lc[x],lc[y],l,m);
rc[x]=merge(rc[x],rc[y],m+,r);
}
sum[x]=sum[x]+sum[y];//////
return x;
}
void bl(int g,int l,int r)
{
if(!g)return;
//printf("g:%d l:%d r:%d s:%d d:%d sum:%d\n",g,l,r,s[g],d[g],sum[g]);
const int m=l+r>>;
bl(lc[g],l,m);bl(rc[g],m+,r);
}
void add(int &g,int l,int r,int x,int y,LL a,LL b)
{
if(l>y||r<x)return;
if(!g)g=++tot;
if(l>=x&&r<=y){
s[g]+=a+b*(l-x);
d[g]+=b;
upd(g,r-l+);
return;
}
const int m=l+r>>;
add(lc[g],l,m,x,y,a,b);
add(rc[g],m+,r,x,y,a,b);
upd(g,r-l+);
}
LL ask(int g,int l,int r,int x,int y)
{
if(!g||l>y||r<x)return ;
if(l>=x&&r<=y)return sum[g];
const int m=l+r>>;
int tl=max(l,x),tr=min(r,y);
LL ret=cal(s[g]+d[g]*(tl-l),d[g],tr-tl+);
return ret+ask(lc[g],l,m,x,y)+ask(rc[g],m+,r,x,y);
} int dl[N],dr[N],dep[N],tp[N],hs[N],pos[N],f[N],sz[N];
inline void dfs1(int g,int fa){
dep[g]=dep[fa]+;sz[g]=;f[g]=fa;
for(int i=he[g];i;i=ne[i]){
if(to[i]^fa){
dfs1(to[i],g);
if(sz[to[i]]>sz[hs[g]])hs[g]=to[i];
sz[g]+=sz[to[i]];
}
}
}
inline void dfs2(int g,int fa){
dl[g]=dr[g]=++cnt;pos[cnt]=g;
tp[g]=g==hs[fa]?tp[fa]:g;
if(hs[g])dfs2(hs[g],g);
for(int i=he[g];i;i=ne[i])
if(!dl[to[i]])dfs2(to[i],g);
}
inline int LCA(int x,int y){
while(tp[x]!=tp[y]){
if(dep[tp[x]]>dep[tp[y]])swap(x,y);
y=f[tp[y]];
}
if(dep[x]<dep[y])return x;return y;
} inline void work(int &g,int fr,int to,LL a,LL b)
{
if(dep[fr]<dep[to])return;
while(tp[fr]!=tp[to]){
add(g,,n,dl[tp[fr]],dl[fr],a+b*(dl[fr]-dl[tp[fr]]),-b);
a+=b*(dl[fr]-dl[tp[fr]]+);
fr=f[tp[fr]];
}
add(g,,n,dl[to],dl[fr],a+b*(dl[fr]-dl[to]),-b);
}
inline LL getans(int g,int fr,int to)
{
LL ret=;
while(tp[fr]!=tp[to]){
ret+=ask(g,,n,dl[tp[fr]],dl[fr]);
fr=f[tp[fr]];
}
ret+=ask(g,,n,dl[to],dl[fr]);
return ret;
}
main()
{ scanf("%lld%lld",&n,&m);
for(int i=,x,y;i<n;++i){
scanf("%lld%lld",&x,&y);
addedge(x,y);addedge(y,x);
}
cnt=;dfs1(,);dfs2(,);
char s[];int x,y,a,b;LL lasans=,ts=,now=;
while(m--)
{
scanf("%s",s);
if(s[]=='c'){
scanf("%lld%lld%lld%lld",&x,&y,&a,&b);
x^=lasans;y^=lasans;
++ts;
int lca=LCA(x,y),dis=dep[x]+dep[y]-dep[lca]-dep[lca];
// printf("%d %d %d\n",x,y,lca);
work(rt[ts],x,lca,a,b);
work(rt[ts],y,lca,a+b*dis,-b);
add(rt[ts],,n,dl[lca],dl[lca],-(a+(dep[x]-dep[lca])*b),);
rt[ts]=merge(rt[ts],rt[now],,n);
// bl(rt[ts],1,n);
now=ts;
}
else if(s[]=='q'){
scanf("%lld%lld",&x,&y);
x^=lasans;y^=lasans;
int lca=LCA(x,y);
lasans=getans(rt[now],x,lca)+getans(rt[now],y,lca)-getans(rt[now],lca,lca);
printf("%lld\n",lasans);
}
else{
scanf("%lld",&now);
now^=lasans;
}
}
return ;
}
T5:Alo
此题考察可持久化trie+RMQ
因为要取区间次大值,所以要找出以每个数作次大值的区间即可,
对于每个数,先找到右面第一个比它大的,然后再向右找到第二个比它大的,这个过程可以用二分+rmq实现,这样就得到了它作为次大值的右端点,reverse一下就得到了左端点,用trie在区间找到最值即可
T5:最大异或和
可持久化trie的板子题
可持久化数据结构(平衡树、trie树、线段树) 总结的更多相关文章
- 浅谈可持久化Trie与线段树的原理以及实现(带图)
浅谈可持久化Trie与线段树的原理以及实现 引言 当我们需要保存一个数据结构不同时间的每个版本,最朴素的方法就是每个时间都创建一个独立的数据结构,单独储存. 但是这种方法不仅每次复制新的数据结构需要时 ...
- 浅谈树套树(线段树套平衡树)&学习笔记
0XFF 前言 *如果本文有不好的地方,请在下方评论区提出,Qiuly感激不尽! 0X1F 这个东西有啥用? 树套树------线段树套平衡树,可以用于解决待修改区间\(K\)大的问题,当然也可以用 ...
- POJ2104 K-th Number 不带修改的主席树 线段树
http://poj.org/problem?id=2104 给定一个序列,求区间第k小 通过构建可持久化的点,得到线段树左儿子和右儿子的前缀和(前缀是这个序列从左到右意义上的),然后是一个二分的ge ...
- BZOJ_3196_二逼平衡树_(树套树,线段树+Treap)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=3196 可以处理区间问题的平衡树. 3196: Tyvj 1730 二逼平衡树 Time Lim ...
- cogs 1829. [Tyvj 1728]普通平衡树 权值线段树
1829. [Tyvj 1728]普通平衡树 ★★★ 输入文件:phs.in 输出文件:phs.out 简单对比时间限制:1 s 内存限制:1000 MB [题目描述] 您需要写一种数 ...
- COJ 1010 WZJ的数据结构(十) 线段树区间操作
传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001 WZJ的数据结构(十) 难度级别:D: 运行时间限制:3000ms: ...
- 1588. [HNOI2002]营业额统计【平衡树-splay 或 线段树】
Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger拿出了公司的账本,账本上记录了公司成立以来每 ...
- 洛谷 P3285 / loj 2212 [SCOI2014] 方伯伯的 OJ 题解【平衡树】【线段树】
平衡树分裂钛好玩辣! 题目描述 方伯伯正在做他的 OJ.现在他在处理 OJ 上的用户排名问题. OJ 上注册了 \(n\) 个用户,编号为 \(1\sim n\),一开始他们按照编号排名.方伯伯会按照 ...
- [BZOJ3196] 二逼平衡树 [权值线段树套位置平衡树]
题面 洛咕题面 思路 没错我就是要不走寻常路! 看看那些外层位置数据结构,必须二分的,$O(n\log^3 n)$的做法吧! 看看那些cdq分治/树状数组套线段树的,空间$O(n\log^2 n)$挤 ...
随机推荐
- 设计基于HTML5的APP登录功能及安全调用接口的方式(原理篇)
登录 保存密码 安全 加密 最近发现群内大伙对用Hbuilder做的APP怎么做登录功能以及维护登录状态非常困惑,而我前一段时间正好稍微研究了一下,所以把我知道的告诉大家,节约大家查找资料的时间. 你 ...
- Tomcat一闪而过的调试方法
很少用tomcat来部署,都是用springboot微服务.只是以前学的时候搞demo试过而已. 软件测试的期末作业要求要测一个Javaweb的项目,给了一个包然后要求部署在tomcat中并启动. 然 ...
- 编写Postgres扩展之三:调试
原文:http://big-elephants.com/2015-10/writing-postgres-extensions-part-iii/ 编译:Tacey Wong 在上一篇关于编写Post ...
- Python爬虫之BeautifulSoap的用法
1. Beautiful Soup的简介 简单来说,Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据.官方解释如下: Beautiful Soup提供一些简单的.pyt ...
- restTemplate源码解析(目录)
restTemplate是spring实现的,基于restful风格的http请求模板.使用restTemplate可以简化请求操作的复杂性,同时规范了代码风格.本系列文章,将根据以下目录顺序,从源码 ...
- va_start可变参数函数
void va_start(va_list ap, last); //变参起始地址 type va_arg(va_list ap, type); //下一个参数的地址 void va_end(va_l ...
- 50个Sql语句实战
/* 说明:以下五十个语句都按照测试数据进行过测试,最好每次只单独运行一个语句. 问题及描述:--1.学生表Student(S#,Sname,Sage,Ssex) --S# 学生编号,Sname 学生 ...
- window.addEventListener('error')监听页面是否更新版本
因本司更新迭代的速度很快,有时候更改一个BUG就要马上更新版本,就会引起用户在应用当中,页面点击无反应,其实是打包的js和css的包名称更改,找不到以前的包的缘故.我现在用一个小方法,判断js或css ...
- 【20191118会议】针对华为云CCE 问题总结
针对华为云CCE问题总结 如何购买CCE集群 可以分为测试环境和生产环境,针对使用范围进行购买集群. 测试环境 可以进行公用 生产环境建议使用单独集群 尤其针对部门大 耦合性不高 ,生产环境 建议使用 ...
- Java 反射原理
一.Java 反射的定义 反射机制是在运行状态中, 对于任意一个类, 都能够知道这个类的所有属性和方法: 对于任意一个对象,都能够调用它的任意一个方法或者属性: 二.反射提供的功能: 在运行时判断任意 ...