bzoj 4448 [Scoi2015]情报传递(主席树,LCA)
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=4448
【题意】
给定一颗树,询问一条路径上权值小于t-c的点数。
【思路】
将一个2查询的出现时间作为该点的权值,按照树的形态建主席树,然后将权值插入,线段树结点中记录该区间的所有点数。
对于一个1查询,即查询u,v路径上权值小于t-c的点数,t为查询的出现时间。在主席树上统计,设ans(x)表示T[x]中小于t-c的点数,答案为ans(u)+ans(v)-ans(lca(u,v))-ans(fa(lca(u,v)))。
【代码】
1 #include<set> 2 #include<cmath> 3 #include<queue> 4 #include<vector> 5 #include<cstdio> 6 #include<cstring> 7 #include<iostream> 8 #include<algorithm> 9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt) 10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 11 using namespace std; 12 13 typedef long long ll; 14 const int N = 2e5+10; 15 16 ll read() { 17 char c=getchar(); 18 ll f=1,x=0; 19 while(!isdigit(c)) { 20 if(c=='-') f=-1; c=getchar(); 21 } 22 while(isdigit(c)) 23 x=x*10+c-'0',c=getchar(); 24 return x*f; 25 } 26 27 struct Edge { 28 int v,nxt; 29 }e[N<<2]; 30 int en=1,front[N]; 31 void adde(int u,int v) 32 { 33 e[++en]=(Edge){v,front[u]}; front[u]=en; 34 } 35 36 struct Tnode { 37 Tnode *ls,*rs; 38 int sum; 39 }*T[N],mempool[N*50],*G=mempool; 40 41 Tnode * Nw(Tnode*l,Tnode*r,int x) { 42 G->ls=l,G->rs=r,G->sum=x; 43 return G++; 44 } 45 Tnode* build(Tnode* p,int l,int r,int pos) { 46 int val=pos==0? p->sum:p->sum+1; 47 if(l==r) 48 return Nw(T[N-1],T[N-1],val); 49 else { 50 int mid=l+r>>1; 51 if(pos<=mid) return Nw(build(p->ls,l,mid,pos),p->rs,val); 52 else return Nw(p->ls,build(p->rs,mid+1,r,pos),val); 53 } 54 } 55 int query(Tnode* x,int l,int r,int pos) 56 { 57 if(l==r) { return x->sum; } 58 else { 59 int mid=l+r>>1; 60 if(pos<=mid) return query(x->ls,l,mid,pos); 61 else return x->ls->sum+query(x->rs,mid+1,r,pos); 62 } 63 } 64 65 int n,m,tot,val[N],que[N][4]; 66 int top[N],son[N],siz[N],dep[N],fa[N]; 67 68 void dfs1(int u,int father) 69 { 70 siz[u]=1; son[u]=0; 71 T[u]=build(T[father],0,m,val[u]); 72 trav(u,i) if(e[i].v!=father) { 73 int v=e[i].v; 74 fa[v]=u; 75 dep[v]=dep[u]+1; 76 dfs1(v,u); 77 siz[u]+=siz[v]; 78 if(siz[v]>siz[son[u]]) son[u]=v; 79 } 80 } 81 void dfs2(int u,int tp) 82 { 83 top[u]=tp; 84 if(son[u]) dfs2(son[u],tp); 85 trav(u,i) if(e[i].v!=fa[u]&&e[i].v!=son[u]) 86 dfs2(e[i].v,e[i].v); 87 } 88 int lca(int u,int v) 89 { 90 while(top[u]!=top[v]) { 91 if(dep[top[u]]<dep[top[v]]) swap(u,v); 92 u=fa[top[u]]; 93 } 94 return dep[u]<dep[v]? u:v; 95 } 96 97 int main() 98 { 99 // freopen("in.in","r",stdin); 100 // freopen("out.out","w",stdout); 101 n=read(); 102 int rt=0,op,x,y,z; 103 FOR(i,1,n) { 104 x=read(); 105 if(!x) rt=i; 106 else adde(x,i); 107 } 108 m=read(); 109 FOR(i,1,m) { 110 op=read(); 111 if(op==2) 112 x=read(),val[x]=i; 113 else { 114 ++tot; 115 que[tot][0]=read(),que[tot][1]=read(),que[tot][2]=read(); 116 que[tot][3]=i; 117 } 118 } 119 dep[rt]=1; 120 T[0]=Nw(G,G,0); 121 T[N-1]=Nw(G,G,0); 122 dfs1(rt,0); 123 dfs2(rt,rt); 124 FOR(i,1,tot) { 125 x=que[i][0],y=que[i][1],z=que[i][2]; 126 int LCA=lca(x,y),ans=dep[x]+dep[y]-dep[LCA]-dep[fa[LCA]]; 127 if(que[i][3]-z-1<=0) printf("%d 0\n",ans); 128 else { 129 int tmp=0; 130 tmp+=query(T[x],0,m,que[i][3]-z-1); 131 tmp+=query(T[y],0,m,que[i][3]-z-1); 132 tmp-=query(T[LCA],0,m,que[i][3]-z-1); 133 tmp-=query(T[fa[LCA]],0,m,que[i][3]-z-1); 134 printf("%d %d\n",ans,tmp); 135 } 136 } 137 return 0; 138 }
posted on 2016-03-29 11:08 hahalidaxin 阅读(294) 评论(0) 编辑 收藏 举报