山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

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  阅读(291)  评论(0编辑  收藏  举报