博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Bzoj3626 [LNOI2014]LCA
阅读量:6574 次
发布时间:2019-06-24

本文共 3644 字,大约阅读时间需要 12 分钟。

先把问题简化,怎样求一个点x和y的lca的deep和

显然直接求LCA,但是这样的话,要求多个就不好叠加
于是可以用奇技淫巧:先把x到根的所有点打上标记,那么询问y到根的标记的个数即为答案,这样就可以叠加
所以对于询问,拆成[1,l-1], [1, r],排序后依次加点覆盖标记即可

可以用树链剖分+线段树,或者Orz yyb大佬一样写LCT

代码

表示不想写LCT

# include 
# define RG register# define IL inline# define Fill(a, b) memset(a, b, sizeof(a))using namespace std;typedef long long ll;const int _(1e5 + 10), __(1e6 + 10), INF(2e9), MOD(201314);IL ll Read(){ char c = '%'; ll x = 0, z = 1; for(; c > '9' || c < '0'; c = getchar()) if(c == '-') z = -1; for(; c >= '0' && c <= '9'; c = getchar()) x = x * 10 + c - '0'; return x * z;}int n, q, cnt, fst[_], to[_], nxt[_], fa[_], son[_], size[_], top[_], deep[_], dfn[_];int sum[__], tag[__], ans[_], z[_];struct Data{ int f, id, type; IL bool operator <(RG Data B) const{ return f < B.f; }} qry[_];IL void Add(RG int u, RG int v){ to[cnt] = v; nxt[cnt] = fst[u]; fst[u] = cnt++; }IL void Dfs1(RG int u){ size[u] = 1; for(RG int e = fst[u]; e != -1; e = nxt[e]){ if(size[to[e]]) continue; deep[to[e]] = deep[u] + 1; fa[to[e]] = u; Dfs1(to[e]); size[u] += size[to[e]]; if(size[to[e]] > size[son[u]]) son[u] = to[e]; }}IL void Dfs2(RG int u, RG int Top){ top[u] = Top; dfn[u] = ++cnt; if(son[u]) Dfs2(son[u], Top); for(RG int e = fst[u]; e != -1; e = nxt[e]) if(!dfn[to[e]]) Dfs2(to[e], to[e]);}IL void Update(RG int x){ sum[x] = (sum[x << 1] + sum[x << 1 | 1]) % MOD; }IL void Pushdown(RG int x, RG int l, RG int r){ if(!tag[x]) return; RG int mid = (l + r) >> 1, ls = x << 1, rs = x << 1 | 1; (sum[ls] += (mid - l + 1) * tag[x]) %= MOD; (sum[rs] += (r - mid) * tag[x]) %= MOD; tag[ls] += tag[x]; tag[rs] += tag[x]; tag[x] = 0;}IL void Modify(RG int x, RG int l, RG int r, RG int L, RG int R){ if(L <= l && R >= r){ (sum[x] += r - l + 1) %= MOD; tag[x]++; return; } Pushdown(x, l, r); RG int mid = (l + r) >> 1; if(L <= mid) Modify(x << 1, l, mid, L, R); if(R > mid) Modify(x << 1 | 1, mid + 1, r, L, R); Update(x);}IL int Query(RG int x, RG int l, RG int r, RG int L, RG int R){ if(L <= l && R >= r) return sum[x]; Pushdown(x, l, r); RG int mid = (l + r) >> 1, Ans = 0; if(L <= mid) Ans = Query(x << 1, l, mid, L, R); if(R > mid) Ans += Query(x << 1 | 1, mid + 1, r, L, R); Update(x); return Ans;}IL void Cover(RG int x, RG int y){ while(top[x] != top[y]){ if(deep[top[x]] < deep[top[y]]) swap(x, y); Modify(1, 1, n, dfn[top[x]], dfn[x]); x = fa[top[x]]; } if(deep[x] < deep[y]) swap(x, y); Modify(1, 1, n, dfn[y], dfn[x]);}IL int Calc(RG int x, RG int y){ RG int Ans = 0; while(top[x] != top[y]){ if(deep[top[x]] < deep[top[y]]) swap(x, y); Ans += Query(1, 1, n, dfn[top[x]], dfn[x]); x = fa[top[x]]; } if(deep[x] < deep[y]) swap(x, y); Ans += Query(1, 1, n, dfn[y], dfn[x]); return Ans;}int main(RG int argc, RG char *argv[]){ n = Read(); q = Read(); Fill(fst, -1); for(RG int i = 2, a; i <= n; ++i) a = Read() + 1, Add(a, i), Add(i, a); Dfs1(1); cnt = 0; Dfs2(1, 1); cnt = 0; for(RG int i = 1; i <= q; ++i){ qry[++cnt].f = Read(); qry[cnt].id = i; qry[cnt].type = -1; qry[++cnt].f = Read() + 1; qry[cnt].id = i; qry[cnt].type = 1; z[i] = Read() + 1; } sort(qry + 1, qry + cnt + 1); for(RG int i = 1, j = 0; i <= cnt; ++i){ while(j < qry[i].f) ++j, Cover(1, j); ans[qry[i].id] += qry[i].type * Calc(1, z[qry[i].id]); } for(RG int i = 1; i <= q; i++) printf("%d\n", (ans[i] % MOD + MOD) % MOD); return 0;}

转载于:https://www.cnblogs.com/cjoieryl/p/8206336.html

你可能感兴趣的文章
javascript详解函数原型对象prototype与constructor
查看>>
关键字,标识符,包
查看>>
How to include cascading style sheets (CSS) in JSF
查看>>
Scrum Meeting博客目录
查看>>
python基础: day4作业计算器
查看>>
Java集合--WeakHashMap
查看>>
c#程序 获取类的属性和方法
查看>>
notepad++列编辑操作
查看>>
2015年2月3日
查看>>
LI 导航
查看>>
交流:Ghost版系统安装简单分析
查看>>
简单的jquery代码实现图片轮播
查看>>
IDEA的常用配置一键导入及优化内存
查看>>
keytool 错误 java.io.IOException: incorrect AVA format
查看>>
$.ajax()方法详解(转)
查看>>
java 冒泡排序
查看>>
【CSS】Table样式
查看>>
Qt Quick编程(1)——QML的核心部分ECMAScript
查看>>
js 替换非法字符
查看>>
(转)C# Winform应用程序占用内存较大解决方法整理
查看>>