BZOJ 4448 情报传递
Posted ziliuziliu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 4448 情报传递相关的知识,希望对你有一定的参考价值。
注意到可以转化为静态。直接建树上主席树。
1A了赞。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxv 200500 #define maxe 400500 using 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 情报传递的主要内容,如果未能解决你的问题,请参考以下文章