bzoj 3626 LCA
这一道题咋一看只觉得是离线,可以求出所有的f(1,i,z), 答案就等于f(1,r,z)-f(1,l-1,z)。但是没有具体的做法,但是求LCA的深度和有一个非常巧妙的做法,每加一个点,就把这个点到根的路径上的点权值+1,这样计算某个点和之前所有点LCA深度和就可以统计这个点到根的路径上的点的权值和。这样就可以用树链剖分很快的修改和得出答案,这题就解决了。
上代码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#define N 51000
#define yu 201314
using namespace std; struct sss
{
int place, askp;
int num, nump;
}ask[N*];
struct ss
{
int num, push;
}t[N*];
int n, m, nowplace = ;
int p[N], v[N], next[N], bnum = ;
int ans[N][] = {};
int fa[N], deep[N], siz[N], son[N], w[N], top[N]; bool cmp(sss x, sss y) { return x.place < y.place; } void addbian(int x, int y)
{
bnum++; next[bnum] = p[x]; p[x] = bnum; v[bnum] = y;
} void build_tree(int now, int l, int r)
{
t[now].num = ; t[now].push = ;
if (l == r) return; int mid = (l+r)/;
build_tree(now*, l, mid); build_tree(now*+, mid+, r);
} void dfs_1(int now, int fat, int de)
{
int k = p[now]; fa[now] = fat; deep[now] = de;
int maxsonnum = ; siz[now] = ; son[now] = ;
while (k)
{
if (v[k] != fat)
{
dfs_1(v[k], now, de+);
siz[now] += siz[v[k]];
if (siz[v[k]] > maxsonnum)
{
maxsonnum = siz[v[k]];
son[now] = v[k];
}
}
k = next[k];
}
return;
} void dfs_2(int now, int fat, int nowtop)
{
int k = p[now]; top[now] = nowtop; w[now] = ++nowplace;
if (son[now]) dfs_2(son[now], now, nowtop);
while (k)
{
if (v[k] != son[now] && v[k] != fat)
dfs_2(v[k], now, v[k]);
k = next[k];
}
return;
} void downdate(int now, int l, int r)
{
if (!t[now].push) return; int mid = (l+r)/;
t[now*].push += t[now].push;
t[now*+].push += t[now].push;
t[now*].num += (mid-l+) * t[now].push;
t[now*+].num += (r-mid) * t[now].push;
if (t[now*].num > yu) t[now*].num %= yu;
if (t[now*+].num > yu) t[now*+].num %= yu;
t[now].push = ; return;
} void tadd(int now, int l, int r, int al, int ar)
{
if (al <= l && r <= ar)
{
t[now].num += r-l+;
if (t[now].num > yu) t[now].num %= yu;
t[now].push ++; return;
}
int mid = (l+r)/; downdate(now, l, r);
if (al <= mid) tadd(now*, l, mid, al, ar);
if (ar > mid) tadd(now*+, mid+, r, al, ar);
t[now].num = t[now*].num + t[now*+].num;
if (t[now].num > yu) t[now].num %= yu;
} int task(int now, int l, int r, int al, int ar)
{
if (al <= l && r <= ar) return t[now].num;
int mid = (l+r)/, zans = ; downdate(now, l, r);
if (al <= mid) zans = task(now*, l, mid, al, ar);
if (ar > mid) zans += task(now*+, mid+, r, al, ar);
if (zans > yu) zans %= yu;
return zans;
} int askk(int u, int v)
{
int f1 = top[u], f2 = top[v];
if (deep[f1] < deep[f2]) { swap(f1, f2); swap(u, v); }
if (f1 == f2)
{
if (u == v) return task(, , n, w[u], w[u]);
return task(, , n, min(w[u], w[v]), max(w[u], w[v]));
}
int zans = task(, , n, w[f1], w[u]);
zans += askk(fa[f1], v); if (zans > yu) zans %= yu;
return zans;
} void add(int u, int v)
{
int f1 = top[u], f2 = top[v];
if (deep[f1] < deep[f2]) { swap(f1, f2); swap(u, v); }
if (f1 == f2)
{
if (u == v) tadd(, , n, w[u], w[u]);
else tadd(, , n, min(w[u], w[v]), max(w[u], w[v]));
return;
}
tadd(, , n, w[f1], w[u]); add(fa[f1], v);
} int main()
{
scanf("%d%d", &n, &m); build_tree(, , n);
for (int i = ; i < n; ++i)
{
int x; scanf("%d", &x);
addbian(x+, i+);
}
dfs_1(, , ); dfs_2(, , );
for (int i = ; i <= m; ++i)
{
int x, y, z; scanf("%d%d%d", &x, &y, &z); x++; y++; z++;
ask[i*-].place = x-; ask[i*-].askp = z;
ask[i*-].num = i; ask[i*-].nump = ;
ask[i*].place = y; ask[i*].askp = z;
ask[i*].num = i; ask[i*].nump = ;
}
sort(ask+, ask++*m, cmp); int nowplace = ;
for (int i = ; i <= m*; ++i)
{
while (ask[i].place > nowplace)
{
nowplace++;
add(, nowplace);
}
if (ask[i].place)
ans[ask[i].num][ask[i].nump] = askk(, ask[i].askp);
else ans[ask[i].num][ask[i].nump] = ;
}
for (int i = ; i <= m; ++i)
printf("%d\n", (ans[i][]+yu-ans[i][]) % yu);
return ;
}
bzoj 3626 LCA的更多相关文章
- BZOJ 3626 LCA(离线+树链剖分)
首先注意到这样一个事实. 树上两个点(u,v)的LCA的深度,可以转化为先将u到根路径点权都加1,然后求v到根路径上的总点权值. 并且该题支持离线.那么我们可以把一个区间询问拆成两个前缀和形式的询问. ...
- BZOJ 3626 LCA(离线+树链剖分+差分)
显然,暴力求解的复杂度是无法承受的. 考虑这样的一种暴力,我们把 z 到根上的点全部打标记,对于 l 到 r 之间的点,向上搜索到第一个有标记的点求出它的深度统计答案.观察到,深度其实就是上面有几个已 ...
- [BZOJ 3626] [LNOI2014] LCA 【树链剖分 + 离线 + 差分询问】
题目链接: BZOJ - 3626 题目分析 考虑这样的等价问题,如果我们把一个点 x 到 Root 的路径上每个点的权值赋为 1 ,其余点的权值为 0,那么从 LCA(x, y) 的 Depth 就 ...
- BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2050 Solved: 817[Submit][Status ...
- bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1272 Solved: 451[Submit][Status ...
- bzoj 3626: [LNOI2014]LCA 离线+树链剖分
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 426 Solved: 124[Submit][Status] ...
- BZOJ 3626: [LNOI2014]LCA( 树链剖分 + 离线 )
说多了都是泪啊...调了这么久.. 离线可以搞 , 树链剖分就OK了... -------------------------------------------------------------- ...
- BZOJ 3626 [LNOI2014]LCA:树剖 + 差分 + 离线【将深度转化成点权之和】
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3626 题意: 给出一个n个节点的有根树(编号为0到n-1,根节点为0,n <= 50 ...
- BZOJ 3626 [LNOI2014]LCA 树剖+(离线+线段树 // 在线+主席树)
BZOJ 4012 [HNOI2015]开店 的弱化版,离线了,而且没有边权(长度). 两种做法 1 树剖+离线+线段树 这道题求的是一个点zzz与[l,r][l,r][l,r]内所有点的lcalca ...
随机推荐
- C++中使用union的几点思考(转)
C++中使用union的几点思考 大卫注:这段时间整理旧资料,看到一些文章,虽然讲的都是些小问题,不大可能用到,但也算是一个知识点,特整理出来与大家共享.与此相关的那篇文章的作者的有些理解是错误的,我 ...
- Sublime Text 备忘
Sublime Text已经被传成编程利器,那当然也是我们前端的利器了,刚开始用的时候,很多小问题,所以做个备忘,忘记的时候也可以翻出来看看,下次重装的时候可以用到. 1.设置自动换行 菜单栏 Vie ...
- Angular 1.2.27在IE7下的兼容问题
最近负责公司的一个国外项目,老外指定要用angular,并且要兼容到IE7. 项目使用的是Angular版本是1.2.27,为了能在IE7下跑,需要做如下配置 1. 加载json2.js 2. 加载h ...
- 查看修改swap空间大小
1 查看swap 空间大小(总计): # free -m 默认单位为k, -m 单位为M total used fr ...
- Ruby on Rails Tutorial 第一章 之 搭建开发环境
云端开发环境,Cloud9(https://ide.c9.io/).这个开发环境预先安装好了Rails开发所需要的大多数软件,包括Ruby.RubyGems和Git,需要自己安装Rails. 1.安装 ...
- How to Check if an Array Contains a Value in Java Efficiently?---reference
How to check if an array (unsorted) contains a certain value? This is a very useful and frequently u ...
- Android 高级UI设计笔记09:Android如何实现无限滚动列表
ListView和GridView已经成为原生的Android应用实现中两个最流行的设计模式.目前,这些模式被大量的开发者使用,主要是因为他们是简单而直接的实现,同时他们提供了一个良好,整洁的用户体验 ...
- Java基础知识强化之网络编程笔记23:Android网络通信之 Volley(Google开源网络通信库)
联合网上资料学习:http://www.open-open.com/lib/view/open1451223702339.html 一.Volley的介绍 1. Volley简介 在这之前,我们在程序 ...
- 防止vuejs在解析时出现闪烁
---## 防止vuejs在解析时出现闪烁 ## 原因: 在使用vuejs.angularjs开发时,经常会遇见在如Chrome这类能够快速解析的浏览器上出现表达式({{ express }} ),或 ...
- CSS 实现行内和上下自适应的几种方法
在写一个移动端网页,发现网页的头部搜索框两边各有固定宽度的按钮,搜索框可以根据宽度的变化来改变自己的宽度,达到填充的目的,也就是一种自适应吧,下面写写自己尝试的几种方法 一 利用css3 的width ...