bzoj 3626
http://www.lydsy.com/JudgeOnline/problem.php?id=3626
让我比较惊讶的一道链剖裸题(' ' ) 做法很精妙
首先我们考虑对于单个询问时可以拆分成(1, l - 1, z) 和 (1, r, z) 的, 然后考虑对于每一次询问可以表示为将(1, l) 的所有点到根的全部加1 然后求z到根路径的的和。 所以将询问离线, 按询问的l值排序,每一次遇到新的l值就将这一段的点到根的路径全部加1,然后查询即可
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std; typedef long long ll;
const ll maxn = 100001;
const ll mod = 201314; ll n, m; ll int_get() {
ll x = 0; char c = (char)getchar(); bool f = 0;
while(!isdigit(c)) {
if(c == '-') f = 1;
c = (char)getchar();
}
while(isdigit(c)) {
x = x * 10 + (int)(c - '0');
c = (char)getchar();
}
if(f) x = -x;
return x;
} struct seg {
ll data, lazy;
seg *l, *r;
}tr[maxn * 3];ll sege = 0;
seg* root; void test(seg* x, ll l, ll r) {
cout << l <<" "<< r <<" "<< x-> data <<" "<< x-> lazy << endl;
if(l ^ r) {
ll mid = (l + r) >> 1;
test(x-> l, l, mid), test(x-> r, mid + 1, r);
}
} seg* build(ll l, ll r) {
seg* x = tr + sege ++;
if(l ^ r) {
ll mid = (l + r) >> 1;
x-> l = build(l, mid);
x-> r = build(mid + 1, r);
}
return x;
} void update(seg* x) {
if(x-> l) x-> data = x-> l-> data + x-> r-> data;
} void pushdown(seg* x, ll l, ll r) {
if(x-> l && x-> lazy != 0) {
ll mid = (l + r) >> 1;
x-> l-> lazy += x-> lazy, x-> l-> data += (mid - l + 1) * x-> lazy;
x-> r-> lazy += x-> lazy, x-> r-> data += (r - mid) * x-> lazy;
x-> lazy = 0;
}
} void addlazy(seg* x, ll l, ll r, ll ls, ll rs, ll v) {
if(l == ls && r == rs) x-> data += v * (rs - ls + 1), x-> lazy += v;
else {
pushdown(x, l, r);
ll mid = (l + r) >> 1;
if(rs <= mid) addlazy(x-> l, l, mid, ls, rs, v);
else if(ls > mid) addlazy(x-> r, mid + 1, r, ls, rs, v);
else addlazy(x-> l, l, mid, ls, mid, v), addlazy(x-> r, mid + 1, r, mid + 1, rs, v);
update(x);
}
} ll ask(seg* x, ll l, ll r, ll ls, ll rs) {
if(l == ls && r == rs) return x-> data;
else {
pushdown(x, l, r);
ll mid = (l + r) >> 1;
if(rs <= mid) return ask(x-> l, l, mid, ls, rs);
else if(ls > mid) return ask(x-> r, mid + 1, r, ls, rs);
else return ask(x-> l, l, mid, ls, mid) + ask(x-> r, mid + 1, r, mid + 1, rs);
}
} struct edge {
ll t;
edge* next;
}e[maxn * 2], *head[maxn]; ll ne = 0; void addedge(ll f, ll t) {
e[ne].t = t, e[ne].next = head[f], head[f] = e + ne ++;
} ll h[maxn], size[maxn], fa[maxn], un[maxn], map[maxn], num = 0; void dfs(ll x, ll pre) {
fa[x] = pre, size[x] = 1; h[x] = h[pre] + 1;
for(edge* p = head[x]; p; p = p-> next) {
if(p-> t != pre) dfs(p-> t, x), size[x] += size[p-> t];
}
} void divide(ll x, ll Un) {
un[x] = Un, map[x] = ++ num;
if(size[x] == 1) return ;
ll Max = 0, pos;
for(edge* p = head[x]; p; p = p-> next) {
if(p-> t != fa[x] && size[p-> t] > Max) Max = size[p-> t], pos = p-> t;
}
divide(pos, Un);
for(edge* p = head[x]; p; p = p-> next) {
if(p-> t != fa[x] && p-> t != pos) divide(p-> t, p-> t);
}
} void add(ll a, ll b, ll v) {
ll ls, rs;
while(un[a] != un[b]) {
if(h[un[a]] > h[un[b]]) {
ls = map[un[a]], rs = map[a];
addlazy(root, 1, n, ls, rs, v);
a = fa[un[a]];
}
else {
ls = map[un[b]], rs = map[b];
addlazy(root, 1, n, ls, rs, v);
b = fa[un[b]];
}
}
ls = map[a], rs = map[b];
if(ls > rs) swap(ls, rs);
addlazy(root, 1, n, ls, rs, v);
} ll get(ll a, ll b) {
ll ret = 0;
ll ls, rs;
while(un[a] != un[b]) {
if(h[un[a]] > h[un[b]]) {
ls = map[un[a]], rs = map[a];
ret += ask(root, 1, n, ls, rs);
a = fa[un[a]];
}
else {
ls = map[un[b]], rs = map[b];
ret += ask(root, 1, n, ls, rs);
b = fa[un[b]];
}
}
ls = map[a], rs = map[b];
if(ls > rs) swap(ls, rs);
ret += ask(root, 1, n, ls, rs);
return ret;
} struct block {
ll x, p, pos, fl;
}o[maxn]; ll oe = 0; bool cmp(block a, block b) {
return a. x < b. x;
} ll ans[maxn]; void read() {
n = int_get(); m = int_get();
for(ll i = 2; i <= n; ++ i) {
ll u = int_get() + 1;
addedge(u, i), addedge(i, u);
}
for(ll i = 1; i <= m; ++ i) {
ll a, b, c;
a = int_get() + 1, b = int_get() + 1, c = int_get() + 1;
++ oe, o[oe]. x = a - 1, o[oe]. p = c, o[oe]. pos = i, o[oe]. fl = -1;
++ oe, o[oe]. x = b, o[oe]. p = c, o[oe].pos = i, o[oe].fl = 1;
}
dfs(1, 0), divide(1, 1);
root = build(1, n);
} void sov() {
sort(o + 1, o + 1 + oe, cmp); ll pl = 0;
for(ll i = 1; i <= oe; ++ i) {
while(pl < o[i]. x) {
++ pl; add(1, pl, 1);
}
//test(root, 1, n); cout << endl;
ans[o[i]. pos] += o[i]. fl * get(1, o[i]. p);
}
for(ll i = 1; i <= m; ++ i) printf("%lld\n", (ans[i] % mod + mod)% mod);
} int main() {
//freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
read();
sov();
return 0;
}
bzoj 3626的更多相关文章
- [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 LNOI的树链剖分题没有HAOI那么水,学到的东西还是很多的. 我如果现场写,很难想出来这种题 ...
- AC日记——[LNOI2014]LCA bzoj 3626
3626 思路: 离线操作+树剖: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 #defin ...
- 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 ...
随机推荐
- 转载--关于FPGA设计数字信号处理电路的心得
FPGA使用的越来越广泛,除了可用于设计控制电路以为,数字信号处理电路更是FPGA的强项和难点.个人可以说才刚刚入门FPGA设计,也做过一些数字信号处理方面的电路设计,记录下个人心得体会. (一)善用 ...
- ADSL(Asymmetric Digital Subscriber Loop)技术
上行带宽,下行带宽 宽带上行下行是指一般ADSL上网方式上行与下行速率,上行就是从电脑上传的速度,下行就是从网络上的主机下载速度,一般下行速率比较高! ADSL(Asymmetric Digital ...
- Acunetix Web Vulnerability Scanner(WVS)(Acunetix网络漏洞扫描器)
Acunetix网络漏洞扫描软件检测您网络的安全性安全测试工具Acunetix Web Vulnerability Scanner(WVS) (Acunetix网络漏洞扫描器)技术 网络应用安全扫描技 ...
- LocalActivityManager如何在一个Activity的一部分中显示其他Activity
首先要使用该方法,页面必须继承ActivityGroup. 总的来说,实现"如何在一个Activity的一部分中显示其他Activity"除了LocalActivityManage ...
- VS2010提示error TRK0002: Failed to execute command
转自VC错误:http://www.vcerror.com/?p=277 问题描述: windows8自动更新Microsoft .NET Framework 3.5和4.5.1安全更新程序,今天用V ...
- 记录MNIST采用卷积方式实现与理解
从时间上来说,这篇文章写的完了,因为这个实验早就做完了:但从能力上来说,这篇文章出现的早了,因为很多地方我都还没有理解.如果不现在写,不知道什么时候会有时间是其一,另外一个原因是怕自己过段时间忘记. ...
- appium常见问题02_android内嵌H5页(webview)如何定位
现在大多数app都是由原生页面和内嵌H5(即webview)组成,app原生页面直接定位即可,那内嵌H5页面要如何定位呢. 相信大多数人用appium做自动化时都有遇到这个问题,小编总结了下工作中该问 ...
- vim如何达到高效
参考:http://blog.jobbole.com/44891/ 搜索技巧 1. 使用*快速查询当前光标所在的单词 然后使用n快速找到下一个查询结果: 使用N快速找到上一个查询结果 2. 在.vim ...
- Java迭代器模式
迭代器模式是Java和.Net编程环境中非常常用的设计模式.此模式用于以顺序方式访问集合对象的元素,而不需要知道其底层表示. 迭代器模式属于行为模式类别. 实现实例 在这个实例中,将创建一个Itera ...
- python3中装饰器的用法总结
装饰器预备知识点 1 函数赋值给一个变量 函数名可以像普通变量一样赋值给另一个变量. def test(): print("i am just a test function") ...