51nod 1681 公共祖先

来源:互联网 发布:js trimend 编辑:程序博客网 时间:2024/05/17 00:57

主席树,让我有点懵逼。。。

//#include<bits/stdc++.h>#include<stdio.h>#include<cstring>using namespace std;void read(int&a){    char ch;while(!((ch=getchar())>='0')&&(ch<='9'));    a=ch-'0';while(((ch=getchar())>='0')&&(ch<='9'))a*=10,a+=ch-'0';}const int MAXN=100100;const int MAXM=2000100;int LS[MAXN],LE[MAXN],RS[MAXN],RE[MAXN];int tmp[MAXN],pos[MAXN],vis[MAXN],head[MAXN],root[MAXN];int tot,sz;struct Edge{int to,nxt;}e[MAXN];struct node{int l,r,c;}tree[MAXM];void init(){tot=0;memset(head,-1,sizeof(head));memset(vis,0,sizeof(vis));}void addedge(int u,int v){e[tot].to=v;e[tot].nxt=head[u];head[u]=tot++;}void dfs(int u,int pre,int flag){if(flag){RS[u]=++sz;//标记u点的dfs序的起点 tmp[sz]=pos[u];//R树中,dfs序所代表的节点,在L树中的dfs序 }else{LS[u]=++sz;//标记u点的dfs序的起点 pos[u]=sz;//L数中,标记u点的dfs序起点位置 }for(int i=head[u];i!=-1;i=e[i].nxt){if(e[i].to!=pre)dfs(e[i].to,u,flag);} if(flag)RE[u]=sz;//标记dfs序的终点。u及其子树的节点,在dfs序中的位置为[LS[u],LE[u]] elseLE[u]=sz;}void update(int &rt,int l,int r,int num){tree[++sz]=tree[rt];rt=sz;tree[rt].c++;if(l==r)return;int mid=(l+r)>>1;if(num<=mid)update(tree[rt].l,l,mid,num);elseupdate(tree[rt].r,mid+1,r,num);}int query(int x,int y,int L,int R,int l,int r){if(L<=l&&R>=r)return tree[y].c-tree[x].c;int mid=(l+r)>>1;int ret=0;if(L<=mid)ret+=query(tree[x].l,tree[y].l,L,R,l,mid);if(R>mid)ret+=query(tree[x].r,tree[y].r,L,R,mid+1,r);return ret; }int main(){long long x,ans;int n,u,v,rot,i;while(~scanf("%d",&n)){tot=0;init();for(i=1;i<n;i++){read(u);read(v);addedge(u,v);vis[v]=1;}sz=0;for(i=1;i<=n;i++){if(!vis[i]){rot=i;break;}}dfs(rot,0,0);init();for(i=1;i<n;i++){read(u);read(v);addedge(u,v);vis[v]=1;}sz=0;for(i=1;i<=n;i++){if(!vis[i]){rot=i;break;}}dfs(rot,0,1);root[0]=0;sz=0;memset(tree,0,sizeof(tree));for(i=1;i<=n;i++){root[i]=root[i-1];update(root[i],1,n,tmp[i]);}ans=0;for(i=1;i<=n;i++){x=query(root[RS[i]-1],root[RE[i]],LS[i],LE[i],1,n);ans+=(x-1)*(x-2)/2;}printf("%lld\n",ans);}}