zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",ans,tmp);
    135         }
    136     }
    137     return 0;
    138 }
  • 相关阅读:
    synchronized 到底该不该用?
    线上Java程序占用 CPU 过高,请说一下排查方法?
    『JVM』我不想知道我是怎么来滴,我就想知道我是怎么没滴
    Golang 实现 Redis(8): TCC分布式事务
    Golang 实现 Redis(7): 集群与一致性 Hash
    Golang 实现 Redis(6): 实现 pipeline 模式的 redis 客户端
    LSM 树详解
    uni-app subNVue 原生子窗体简单使用案例(app端)
    日计不足涓滴成河-自定义响应结果格式化器
    RTT之软件包
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5332182.html
Copyright © 2011-2022 走看看