BZOJ 4012 [HNOI2015]开店 的弱化版,离线了,而且没有边权(长度).

两种做法

1 树剖+离线+线段树

这道题求的是一个点zzz与[l,r][l,r][l,r]内所有点的lcalcalca的深度之和.可以发现,dep[lca(u,v)]dep[lca(u,v)]dep[lca(u,v)]就等于从uuu到根从vvv到根的路径的交集路径的长度.那么只要把[l,r][l,r][l,r]所有点到根的路径标记了,然后用zzz点往根跑统计答案就行了.这样的话差分一下,离线就可以处理了.

时间复杂度O(nlog2n)O(nlog^2n)O(nlog2n)

CODE

#include <vector>
#include <queue>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL; inline void read(int &num) {
char ch; int flg=1; while(!isdigit(ch=getchar()))if(ch=='-')flg=-flg;
for(num=0; isdigit(ch); num=num*10+ch-'0',ch=getchar()); num*=flg;
}
const int MAXN = 50005;
const int mod = 201314; int n, tot, Q, dfn[MAXN], seq[MAXN], tmr, fir[MAXN], cnt;
struct edge { int to, nxt; }e[MAXN]; inline void add(int u, int v) {
e[cnt] = (edge){ v, fir[u] }, fir[u] = cnt++;
}
int dep[MAXN], fa[MAXN], sz[MAXN], top[MAXN], son[MAXN];
void dfs(int u) {
dep[u] = dep[fa[u]] + (sz[u]=1);
for(int v, i = fir[u]; ~i; i = e[i].nxt) {
dfs(v=e[i].to), sz[u] += sz[v];
if(sz[v] > sz[son[u]]) son[u] = v;
}
}
void dfs2(int u, int tp) {
top[u] = tp; dfn[u] = ++tmr;
if(son[u]) dfs2(son[u], tp);
for(int v, i = fir[u]; ~i; i = e[i].nxt)
if((v=e[i].to) != son[u]) dfs2(v, v);
} struct node {
int tim, x, id, flg;
}q[MAXN<<1];
inline bool cmp(const node &A, const node &B) { return A.tim < B.tim; }
int ans[MAXN];
int lz[MAXN<<2], sum[MAXN<<2];
inline void upd(int i) { sum[i] = sum[i<<1] + sum[i<<1|1]; }
inline void mt(int i, int l, int r, int mid) {
if(lz[i]) {
(lz[i<<1] += lz[i]) %= mod;
(lz[i<<1|1] += lz[i]) %= mod;
(sum[i<<1] += 1ll * lz[i] * (mid-l+1) % mod) %= mod;
(sum[i<<1|1] += 1ll * lz[i] * (r-mid) % mod) %= mod;
lz[i] = 0;
}
}
void insert(int i, int l, int r, int x, int y) {
if(l == x && r == y) {
(lz[i] += 1) %= mod;
(sum[i] += r-l+1) %= mod;
return;
}
int mid = (l + r) >> 1;
mt(i, l, r, mid);
if(y <= mid) insert(i<<1, l, mid, x, y);
else if(x > mid) insert(i<<1|1, mid+1, r, x, y);
else insert(i<<1, l, mid, x, mid), insert(i<<1|1, mid+1, r, mid+1, y);
upd(i);
}
int query(int i, int l, int r, int x, int y) {
if(l == x && r == y) return sum[i];
int mid = (l + r) >> 1;
mt(i, l, r, mid);
int res = 0;
if(y <= mid) res = query(i<<1, l, mid, x, y);
else if(x > mid) res = query(i<<1|1, mid+1, r, x, y);
else res = (query(i<<1, l, mid, x, mid) + query(i<<1|1, mid+1, r, mid+1, y)) % mod;
upd(i);
return res;
}
inline void Modify(int x) {
while(x) insert(1, 1, n, dfn[top[x]], dfn[x]), x = fa[top[x]];
}
inline int Query(int x) {
int res = 0;
while(x) (res += query(1, 1, n, dfn[top[x]], dfn[x])) %= mod, x = fa[top[x]];
return res;
} int main() {
read(n); read(Q);
memset(fir, -1, sizeof fir);
for(int i = 2; i <= n; ++i)
read(fa[i]), ++fa[i], add(fa[i], i);
dfs(1); dfs2(1, 1);
for(int i = 1, x, y, z; i <= Q; ++i) {
read(x), read(y), read(z); ++x, ++y, ++z;
q[++tot] = (node){ x-1, z, i, -1 }; //差分
q[++tot] = (node){ y , z, i, 1 };
}
sort(q + 1, q + tot + 1, cmp);
int now = 0;
for(int i = 1; i <= tot; ++i) {
while(now < q[i].tim) Modify(++now);
(ans[q[i].id] += q[i].flg * Query(q[i].x)) %= mod;
}
for(int i = 1; i <= Q; ++i)
printf("%d\n", (ans[i]+mod)%mod);
}

2 树剖+在线+主席树

沿用法1的思路,直接在主席树上找rrr的线段树与l−1l-1l−1的线段树相减就行了.但是主席树不能下传标记,那么就把标记永久化.查询的时候在主席树上从根往下边走边统计.

时间复杂度同样是O(nlog2n)O(nlog^2n)O(nlog2n),常数巨大…

CODE

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
template<typename T>inline void read(T &num) {
char ch; int flg = 1;
while((ch=getchar())<'0'||ch>'9')if(ch=='-')flg=-flg;
for(num=0;ch>='0'&&ch<='9';num=num*10+ch-'0',ch=getchar());
num*=flg;
}
const int MAXN = 50005;
const int mod = 201314;
const int MAXNN = MAXN*100;
int n, q, A, fir[MAXN], cnt;
struct edge { int to, nxt; }e[MAXN];
inline void add(int u, int v) {
e[cnt] = (edge){ v, fir[u] }, fir[u] = cnt++;
} int son[MAXN], sz[MAXN], top[MAXN], tmr, dfn[MAXN], fa[MAXN];
void dfs(int u) {
sz[u] = 1;
for(int i = fir[u], v; ~i; i = e[i].nxt) {
dfs(v=e[i].to), sz[u] += sz[v];
if(sz[v] > sz[son[u]]) son[u] = v;
}
}
void dfs2(int u, int tp) {
top[u] = tp; dfn[u] = ++tmr;
if(son[u]) dfs2(son[u], tp);
for(int i = fir[u], v; ~i; i = e[i].nxt)
if((v=e[i].to) != fa[u] && v != son[u])
dfs2(v, v);
}
int ch[MAXNN][2], tim[MAXNN], tot, rt[MAXN], sum[MAXNN]; inline void Newnode(int i, int p) { ch[i][0] = ch[p][0], ch[i][1] = ch[p][1], sum[i] = sum[p], tim[i] = tim[p]; } void modify(int &i, int l, int r, int L, int R) {
Newnode(++tot, i);
if(L == l && r == R) { (++tim[i = tot]) %= mod; return; }
(sum[i = tot] += R-L+1) %= mod;
int mid = (l + r) >> 1;
if(R <= mid) modify(ch[i][0], l, mid, L, R);
else if(L > mid) modify(ch[i][1], mid+1, r, L, R);
else modify(ch[i][0], l, mid, L, mid), modify(ch[i][1], mid+1, r, mid+1, R);
}
inline void Modify(int &r, int x) { while(x) modify(r, 1, n, dfn[top[x]], dfn[x]), x = fa[top[x]]; }
int query(int i, int l, int r, int L, int R) {
if(!i) return 0;
int res = 1ll * (R-L+1) * tim[i] % mod;
if(L == l && r == R) return (res + sum[i]) % mod;
int mid = (l + r) >> 1;
if(R <= mid) return (res + query(ch[i][0], l, mid, L, R)) % mod;
else if(L > mid) return (res + query(ch[i][1], mid+1, r, L, R)) % mod;
return (res + query(ch[i][0], l, mid, L, mid) + query(ch[i][1], mid+1, r, mid+1, R)) % mod;
}
int Query(int r, int x) { int res = 0; while(x) (res += query(r, 1, n, dfn[top[x]], dfn[x])) %= mod, x = fa[top[x]]; return res; }
int main () {
read(n), read(q);
memset(fir, -1, sizeof fir);
for(int i = 2; i <= n; ++i)
read(fa[i]), ++fa[i], add(fa[i], i);
dfs(1), dfs2(1, 1);
for(int i = 1; i <= n; ++i) Modify(rt[i]=rt[i-1], i);
int L, R, x;
while(q--) {
read(L), read(R), read(x); ++L, ++R, ++x;
printf("%d\n", (Query(rt[R], x) - Query(rt[L-1], x) + mod) % mod);
}
}

BZOJ 3626 [LNOI2014]LCA 树剖+(离线+线段树 // 在线+主席树)的更多相关文章

  1. bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1272  Solved: 451[Submit][Status ...

  2. BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2050  Solved: 817[Submit][Status ...

  3. BZOJ 3626: [LNOI2014]LCA( 树链剖分 + 离线 )

    说多了都是泪啊...调了这么久.. 离线可以搞 , 树链剖分就OK了... -------------------------------------------------------------- ...

  4. bzoj 3626: [LNOI2014]LCA 离线+树链剖分

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 426  Solved: 124[Submit][Status] ...

  5. BZOJ 3626 [LNOI2014]LCA:树剖 + 差分 + 离线【将深度转化成点权之和】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3626 题意: 给出一个n个节点的有根树(编号为0到n-1,根节点为0,n <= 50 ...

  6. [BZOJ 3626] [LNOI2014] LCA 【树链剖分 + 离线 + 差分询问】

    题目链接: BZOJ - 3626 题目分析 考虑这样的等价问题,如果我们把一个点 x 到 Root 的路径上每个点的权值赋为 1 ,其余点的权值为 0,那么从 LCA(x, y) 的 Depth 就 ...

  7. BZOJ 3626 [LNOI2014]LCA ——树链剖分

    思路转化很巧妙. 首先把询问做差分. 然后发现加入一个点就把路径上的点都+1,询问的时候直接询问到根的路径和. 这样和原问题是等价的,然后树链剖分+线段树就可以做了. #include <map ...

  8. HDU 6162 Ch’s gift (树剖 + 离线线段树)

    Ch’s gift Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  9. P4211[BZOJ 3626] [LNOI2014]LCA

    题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1. 设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先. 有q次询问,每 ...

随机推荐

  1. SQLite进阶-9.别名

    我们可以暂时给表或者列重命名为另一个名字,称为别名,重命名只是临时运行时改变,不会改变数据库中的实际的名字. -- 语法 SELECT column_name AS column_alias_name ...

  2. 「java.util.concurrent并发包」之 ReentrantReadWriteLock

    一 引言 在多线程的环境下,对同一份数据进行读写,会涉及到线程安全的问题.比如在一个线程读取数据的时候,另外一个线程在写数据,而导致前后数据的不一致性:一个线程在写数据的时候,另一个线程也在写,同样也 ...

  3. apache2_fastcgi_python

    1. 前言 之前有用的是apache2 + python + jon模块下的cgi, fcgi. 该框架搭建的服务器我没有找到能够让python程序持久运行的方法(作为一个服务). 最近看了篇文档, ...

  4. PAT B1020 月饼(25)

    题目描述 月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼.现给定所有种类月饼的库存量.总售价.以及市场的最大需求量,请你计算可以获得的最大收益是多少. 注意:销售时允许取出一部 ...

  5. ThinkPHP开发api时多级控制器的访问方法

    发开api时,经常会用到thinkphp的多级控制器,访问方法如下: 例如:有v1和v2两个版本的接口 v1:版本控制器(类文件位置为:application/api/controller/v1/Us ...

  6. @Autowired注解与@Qualifier注解搭配使用----解决多实现选择注入问题

    问题:当一个接口实现由两个实现类时,只使用@Autowired注解,会报错,如下图所示 实现类1 实现类2 controller中注入 然后启动服务报错,如下所示: Exception encount ...

  7. Sql 中的索引

    转载:https://www.cnblogs.com/hyd1213126/p/5828937.html

  8. exclipe怎么设置编码为UTF-8

    如果要使插件开发应用能有更好的国际化支持,能够最大程度的支持中文输出,则最好使 Java文件使用UTF-8编码.然而,Eclipse工作空间(workspace)的缺省字符编码是操作系统缺省的编码,简 ...

  9. vs2013nuget版本更新

    记录记录. NuGet 程序包还原失败: “Newtonsoft.Json 12.0.1”程序包需要 NuGet 客户端版本“2.12”或更高版本,但当前的 NuGet 版本为“2.7.40911.2 ...

  10. luogu题解 P2860[USACO冗余路径Redundant Paths] 缩点+桥

    题目链接 https://www.luogu.org/problemnew/show/P2860 https://www.lydsy.com/JudgeOnline/problem.php?id=17 ...