[BZOJ]4448: [Scoi2015]情报传递 主席树+LCA
来源:互联网 发布:java车辆管理系统源码 编辑:程序博客网 时间:2024/06/05 19:02
Description
奈特公司是一个巨大的情报公司,它有着庞大的情报网络。情报网络中共有n名情报员。每名情报员口J-能有若T名(可能没有)下线,除1名大头日外其余n-1名情报员有且仅有1名上线。奈特公司纪律森严,每名情报员只能与自己的上、下线联系,同时,情报网络中仟意两名情报员一定能够通过情报网络传递情报。奈特公司每天会派发以下两种任务中的一个任务:
1.搜集情报:指派T号情报员搜集情报
2.传递情报:将一条情报从X号情报员传递给Y号情报员
情报员最初处于潜伏阶段,他们是相对安全的,我们认为此时所有情报员的危险值为0;-旦某个情报员开始搜集情报,他的危险值就会持续增加,每天增加1点危险值(开始搜集情报的当天危险值仍为0,第2天危险值为1,第3天危险值为2,以此类推)。传递情报并不会使情报员的危险值增加。为了保证传递情报的过程相对安全,每条情报都有一个风险控制值C。余特公司认为,参与传递这条情报的所有情报员中,危险值大于C的情报员将对该条情报构成威胁。现在,奈特公司希望知道,对于每个传递情报任务,参与传递的情报员有多少个,其中对该条情报构成威胁的情报员有多少个。
题解:
离线乱搞,搜集情报的话就把那个点赋值为当前是第几次询问,传递情报的话第一问就LCA,第二问就找路径上有多少个权值小于等于i-q[i].c-1的点,这个自己想想很快就明白了,至于如何找,就用主席树,每个点一颗树维护当前点到根上的信息,乱搞搞就好了。
代码:
#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>using namespace std;const int maxn=200010;struct Edge{int y,next;}e[maxn];int len=0,last[maxn];int dep[maxn],fa[maxn][20];int lc[maxn*25],rc[maxn*25],s[maxn*25],root[maxn],cnt=0,o[maxn];void ins(int x,int y){ int t=++len; e[t].y=y;e[t].next=last[x];last[x]=t;}int n,Q,Root;void ins(int &u,int l,int r,int p){ if(!u)u=++cnt; s[u]++; if(l==r)return; int mid=l+r>>1; if(p<=mid)ins(lc[u],l,mid,p); else ins(rc[u],mid+1,r,p);}void merge(int &u1,int u2){ if(!u1){u1=u2;return;} if(!u2)return; s[u1]+=s[u2]; merge(lc[u1],lc[u2]); merge(rc[u1],rc[u2]);}void dfs(int x){ for(int i=1;(1<<i)<=dep[x];i++)fa[x][i]=fa[fa[x][i-1]][i-1]; if(o[x])ins(root[x],1,Q,o[x]); merge(root[x],root[fa[x][0]]); for(int i=last[x];i;i=e[i].next) { int y=e[i].y; fa[y][0]=x;dep[y]=dep[x]+1; dfs(y); }}int lca(int x,int y){ if(dep[x]<dep[y])swap(x,y); for(int i=18;i>=0;i--) if((1<<i)<=dep[x]-dep[y])x=fa[x][i]; if(x==y)return x; for(int i=18;i>=0;i--) if((1<<i)<=dep[x]&&fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0];}struct Ask{int op,x,y,c;}q[maxn];int query(int rt1,int rt2,int rt3,int rt4,int l,int r,int k){ int mid=l+r>>1,c=s[lc[rt3]]+s[lc[rt4]]-s[lc[rt1]]-s[lc[rt2]]; if(l==r) { if(l<=k)return s[rt3]+s[rt4]-s[rt1]-s[rt2]; else return 0; } if(k<=mid)return query(lc[rt1],lc[rt2],lc[rt3],lc[rt4],l,mid,k); else return c+query(rc[rt1],rc[rt2],rc[rt3],rc[rt4],mid+1,r,k);}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) { int x; scanf("%d",&x); if(!x)Root=i; else ins(x,i); } scanf("%d",&Q); for(int i=1;i<=Q;i++) { scanf("%d%d",&q[i].op,&q[i].x); if(q[i].op==1)scanf("%d%d",&q[i].y,&q[i].c); else o[q[i].x]=i; } dep[Root]=1;fa[Root][0]=0;dfs(Root); for(int i=1;i<=Q;i++) if(q[i].op==1) { int g=lca(q[i].x,q[i].y); printf("%d ",dep[q[i].x]+dep[q[i].y]-2*dep[g]+1); printf("%d\n",query(root[g],root[fa[g][0]],root[q[i].x],root[q[i].y],1,Q,i-q[i].c-1)); }}
阅读全文
2 0
- 【BZOJ 4448】 [Scoi2015]情报传递|倍增LCA|主席树
- [BZOJ]4448: [Scoi2015]情报传递 主席树+LCA
- bzoj 4448: [Scoi2015]情报传递 (树上主席树)
- BZOJ 4448: [Scoi2015]情报传递 树剖套主席树
- bzoj 4448: [Scoi2015]情报传递
- 4448: [Scoi2015]情报传递 dfs序+主席树
- 4448: [Scoi2015]情报传递|主席树|离线操作
- 【BZOJ 4448】 [Scoi2015]情报传递|树链剖分|树套树
- 4448: [Scoi2015]情报传递
- [BZOJ4448][Scoi2015]情报传递(树上主席树)
- [BZOJ4448][Scoi2015]情报传递(树上主席树)
- bzoj 4448: [Scoi2015]情报传递 dfs序列&树状数组
- 【bzoj 4448】 [Scoi2015]情报传递 离线+树剖+树状数组
- bzoj 4448: [Scoi2015]情报传递 可持久化线段树+离线
- bzoj4448: [Scoi2015]情报传递
- 【bzoj4448】【SCOI2015】情报传递
- BZOJ 2588 LCA + 主席树
- bzoj4448 [Scoi2015]情报传递 树链剖分+树状数组
- linux命令
- 布隆过滤器(Bloom Filter)详解
- awk 整理
- ubuntu 下 LNMP git composer 等安装配置资料汇总
- WPF拙见
- [BZOJ]4448: [Scoi2015]情报传递 主席树+LCA
- SPOJ DISUBSTR 后缀数组
- isEmpty 与 null
- floor函数 与 ceil函数
- Spring MVC注解总结
- 2017趋势面试(软件开发)总结
- docker ps 命令学习
- 按下enter键禁止页面刷新
- POJ