首页 > 代码库 > BZOJ 4448 情报传递

BZOJ 4448 情报传递

注意到可以转化为静态。直接建树上主席树。

1A了赞。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define maxv 200500#define maxe 400500using namespace std;int n,g[maxv],nume=0,m,val[maxv],anc[maxv][21],dis[maxv],a,b,c,type,cnt=0,rt;int root[maxv],tot=0,ls[maxv<<4],rs[maxv<<4],sum[maxv<<4];struct edge{    int v,nxt;}e[maxe];struct query{    int x,y,id,c;}q[maxv];void addedge(int u,int v){    e[++nume].v=v;    e[nume].nxt=g[u];    g[u]=nume;}void modify(int last,int &now,int left,int right,int pos){    now=++tot;sum[now]=sum[last]+1;    if (left==right) return;    ls[now]=ls[last];rs[now]=rs[last];    int mid=left+right>>1;    if (pos<=mid) modify(ls[last],ls[now],left,mid,pos);    else modify(rs[last],rs[now],mid+1,right,pos);}void dfs1(int x){    for (int i=g[x];i;i=e[i].nxt)    {        int v=e[i].v;        if (v!=anc[x][0])        {            anc[v][0]=x;dis[v]=dis[x]+1;            dfs1(v);        }    }}void dfs2(int x){    if (val[x]) modify(root[anc[x][0]],root[x],1,m,val[x]);    else root[x]=root[anc[x][0]];    for (int i=g[x];i;i=e[i].nxt)    {        int v=e[i].v;        if (v!=anc[x][0])            dfs2(v);    }}void get_table(){    for (int e=1;e<=20;e++)        for (int i=1;i<=n;i++)            anc[i][e]=anc[anc[i][e-1]][e-1];}void build(int &now,int left,int right){    now=++tot;sum[now]=0;    if (left==right) return;    int mid=left+right>>1;    build(ls[now],left,mid);    build(rs[now],mid+1,right);}void build_tree(){    build(root[0],1,m);    dfs2(rt);}int lca(int x,int y){    for (int e=20;e>=0;e--)    {        if ((dis[anc[x][e]]>=dis[y]) && (anc[x][e]))            x=anc[x][e];    }    if (x==y) return x;    for (int e=20;e>=0;e--)    {        if (anc[x][e]!=anc[y][e])        {            x=anc[x][e];            y=anc[y][e];        }    }    return anc[x][0];}int ask(int n1,int n2,int n3,int n4,int left,int right,int l,int r){    if (l>r) return 0;    if ((left==l) && (right==r))        return sum[n3]+sum[n4]-sum[n1]-sum[n2];    int mid=left+right>>1;    if (r<=mid) return ask(ls[n1],ls[n2],ls[n3],ls[n4],left,mid,l,r);    else if (l>=mid+1) return ask(rs[n1],rs[n2],rs[n3],rs[n4],mid+1,right,l,r);    else return ask(ls[n1],ls[n2],ls[n3],ls[n4],left,mid,l,mid)+ask(rs[n1],rs[n2],rs[n3],rs[n4],mid+1,right,mid+1,r);}void work(int now){    int x=q[now].x,y=q[now].y,id=q[now].id,c=q[now].c;    if (dis[x]<dis[y]) swap(x,y);    int t=lca(x,y);    printf("%d %d\n",dis[x]+dis[y]-dis[t]-dis[anc[t][0]],ask(root[anc[t][0]],root[t],root[x],root[y],1,m,1,id-c-1));}int main(){    scanf("%d",&n);    for (int i=1;i<=n;i++)    {        scanf("%d",&a);        if (a) {addedge(a,i);addedge(i,a);}        else rt=i;    }    dis[rt]=1;dfs1(rt);get_table();    scanf("%d",&m);    for (int i=1;i<=m;i++)    {        scanf("%d",&type);        if (type==1)        {            scanf("%d%d%d",&a,&b,&c);            cnt++;            q[cnt].x=a;q[cnt].y=b;q[cnt].id=i;q[cnt].c=c;        }        else        {            scanf("%d",&a);            val[a]=i;        }    }    build_tree();    for (int i=1;i<=cnt;i++)        work(i);    return 0;}

 

BZOJ 4448 情报传递