BZOJ 4538 [Hnoi2016]网络
来源:互联网 发布:手机足球关注软件 编辑:程序博客网 时间:2024/04/30 10:43
线段树上二分+链交+LCA
这题做法大概有2种,我用的是第二种
1.实际上一条链的贡献是这条链在树上的补集,于是树剖线段树维护树,每一个节点开一个堆维护最大贡献。
2.假设对于一个询问x,二分出一个答案C,若所有≥C的链都经过了x,则显然最终答案<C,否则最终答案≥C。于是离线将所有链按权排序后,建立权值线段树,节点存储子节点的链交,直接在线段树上二分找答案即可,
顺便补充一下如何求链交,网络上求链交的看不懂,于是只好自己脑补一个。
记链为(LCA,a,b),a,b为两端点,链的深度指LCA的深度,定义max(a,b)为取a,b中深度大的,lca(a,b)为取a,b的LCA。
先判断有没有交,方法是判断深度大链的LCA在不在深度小的链上,若不在则无交集。
否则有交,
若LCA1 = LCA2 ,链交的LCA不变,两端点分别取max即可,就不详细说了。
若LCA1 ≠ LCA2,根据脑补+画图可以知道链交的两个端点分别是
a = max( lca(a1,b2), lca(a2,b1) )
b = max( lca(a1,a2), lca(b1,b2) )
这个式子应该具有一般性,可以直接套用(只是常数比较大)
#include<cstdio>#include<algorithm>#define N 200005#define H 20#define reg registerusing namespace std;namespace runzhe2000{ const int INF = 1<<30; int ecnt, last[N], cnt, timer, beg[N], end[N], fa[N], dep[N], list[N*4], que[N], ST[N*4][H], pos[N], log[N*4], bin[H]; struct edge{int next,to;}e[N<<1]; struct opt { int type, a, b, v; }q[N]; struct chain { int lca, a, b; inline bool in(reg int x) { if(lca == 0)return false; else if(lca == -1)return true; return beg[lca] <= beg[x] && beg[x] <= end[lca] &&( (beg[x] <= beg[a] && beg[a] <= end[x]) || (beg[x] <= beg[b] && beg[b] <= end[x]) ); } }; struct seg { int l, r, v, tot; chain c; }t[N*5]; bool cmp(int a, int b){return q[a].v < q[b].v;} void addedge(reg int a, reg int b) { e[++ecnt] = (edge){last[a], b}; last[a] = ecnt; } inline int dep_min(reg int x, reg int y){return dep[x] < dep[y] ? x : y;} inline int dep_max(reg int x, reg int y){return dep[x] > dep[y] ? x : y;} void dfs(int x) { dep[x] = dep[fa[x]] + 1; list[++timer] = x; beg[x] = timer; for(int i = last[x]; i; i = e[i].next) { int y = e[i].to; if(y == fa[x])continue; fa[y] = x; dfs(y); list[++timer] = x; } end[x] = timer; } void build_ST() { dep[0] = INF; bin[0] = 1;for(int i = 1; i < H; i++)bin[i] = bin[i-1] << 1; for(reg int i = 2; i <= timer; i++)log[i] = 1 + log[i>>1]; for(reg int i = 1; i <= timer; i++)ST[i][0] = list[i]; for(reg int j = 1; j < H; j++) for(reg int i = 1; i <= timer; i++) ST[i][j] = dep_min(ST[i][j-1], ST[i+bin[j-1]][j-1]); } int ask_lca(reg int x, reg int y) { if(x==y)return x; reg int a = beg[x], b = beg[y]; if(a>b)swap(a,b); reg int len = b-a+1; return dep_min(ST[a][log[len]], ST[b-bin[log[len]]+1][log[len]]); } void pushup(int x) { int lson = x<<1, rson = x<<1|1, u, v; if(t[lson].c.lca == -1)t[x].c = t[rson].c; else if(t[rson].c.lca == -1)t[x].c = t[lson].c; else if(t[lson].c.lca == 0 || t[rson].c.lca == 0)t[x].c = (chain){0,0,0}; else if(!t[lson].c.in(t[rson].c.lca) && !t[rson].c.in(t[lson].c.lca))t[x].c = (chain){0,0,0}; else if(t[lson].c.lca == t[rson].c.lca) { u = dep_max(ask_lca(t[lson].c.a, t[rson].c.a), ask_lca(t[lson].c.a, t[rson].c.b)); v = dep_max(ask_lca(t[lson].c.b, t[rson].c.a), ask_lca(t[lson].c.b, t[rson].c.b)); t[x].c = (chain){t[lson].c.lca, u, v}; } else { u = dep_max(ask_lca(t[lson].c.a, t[rson].c.b), ask_lca(t[lson].c.b, t[rson].c.a)); v = dep_max(ask_lca(t[lson].c.a, t[rson].c.a), ask_lca(t[lson].c.b, t[rson].c.b)); t[x].c = (chain){ask_lca(u, v), dep_min(u,v), dep_max(u,v)}; } if(t[x].c.lca==-1 || t[x].c.lca==0)t[x].v=-1; else t[x].v=max(t[lson].v, t[rson].v); t[x].tot = t[x<<1].tot + t[x<<1|1].tot; } void build(int x, int l, int r) { t[x].l = l; t[x].r = r; t[x].c = (chain){t[x].v = -1,0,0}; t[x].tot = 0; if(l==r)return; int mid = (l+r)>>1; build(x<<1,l,mid); build(x<<1|1,mid+1,r); } void modify(reg int x, reg int p, reg int id) { if(t[x].l==t[x].r) { if(!id)t[x].c = (chain){-1,0,0}, t[x].v=-1, t[x].tot = 0; else t[x].c = (chain){ask_lca(q[id].a, q[id].b), q[id].a, q[id].b}, t[x].v=q[id].v, t[x].tot = 1; return; } int mid = (t[x].l+t[x].r)>>1; if(p<=mid)modify(x<<1,p,id); else modify(x<<1|1,p,id); pushup(x); } int query(reg int x, reg int p) { if(t[x].l == t[x].r)return t[x].c.in(p)?-1:t[x].v; else if(!t[x<<1|1].c.in(p))return query(x<<1|1,p); else return query(x<<1,p); } void main() { int n, m; scanf("%d%d",&n,&m); for(reg int i = 1, a, b; i < n; i++) { scanf("%d%d",&a,&b); addedge(a,b); addedge(b,a); } dfs(1); build_ST(); for(reg int i = 1; i <= m; i++) { scanf("%d",&q[i].type); if(q[i].type == 0) { que[++cnt] = i; scanf("%d%d%d",&q[i].a,&q[i].b,&q[i].v); } else if(q[i].type == 1) scanf("%d",&q[i].v); else scanf("%d",&q[i].v); } sort(que+1,que+cnt+1,cmp); for(reg int i = 1; i <= cnt; i++)pos[que[i]] = i; if(cnt)build(1,1,cnt); for(reg int i = 1; i <= m; i++) { if(q[i].type == 0) modify(1,pos[i],i); else if(q[i].type == 1) modify(1,pos[q[i].v],0); else { if(!t[1].tot || t[1].c.in(q[i].v))printf("-1\n"); else printf("%d\n",query(1,q[i].v)); } } }}int main(){ runzhe2000::main();}
0 0
- BZOJ 4538: [Hnoi2016]网络
- bzoj 4538: [Hnoi2016]网络
- BZOJ 4538 [Hnoi2016]网络
- bzoj 4538: [Hnoi2016]网络
- bzoj 4538: [Hnoi2016]网络 树链剖分
- 【BZOJ 4538】[Hnoi2016]网络 树链剖分+堆
- bzoj 4538: [Hnoi2016]网络 树链剖分+线段树
- [树链剖分 线段树 堆] BZOJ 4538 [Hnoi2016]网络
- bzoj 4538: [Hnoi2016]网络 (整体二分+树状数组)
- 4538: [Hnoi2016]网络
- HNOI2016 网络
- HNOI2016 网络
- [HNOI2016] 网络
- BZOJ 4539: [Hnoi2016]树
- BZOJ 4542: [Hnoi2016]大数
- BZOJ 4537: [Hnoi2016]最小公倍数
- BZOJ 4541: [Hnoi2016]矿区
- bzoj 4537: [Hnoi2016]最小公倍数
- 商盾商标查询接口缓慢原因
- 在摄像机视线内问题
- Java转换字符
- 11持有对象
- Apache Apollo配置文件解析(mqtt)
- BZOJ 4538 [Hnoi2016]网络
- Jenkins入门教程之--Jenkins管理
- Linux 文件夹的增删改查
- html文件的script标签用法
- [Android NDK.01] 启程
- SRAM、DRAM、NorFlash、NandFlash
- 理论到实践,A/B测试不得不直面的4个统计学问题
- 什么是时间导数(Time derivative)
- android源码资源