3572: [Hnoi2014]世界树 虚树+DP

来源:互联网 发布:mac系统怎么看文件大小 编辑:程序博客网 时间:2024/06/04 23:06

虚树裸题,正反DP一遍求答案。
写了一发rmqlca发现比倍增慢。。这个显然调用超过n次了啊。。为什么O(nlogn)预处理O(1)查询会比超过nO(logn)查询慢?
bzoj傻逼样例没空格,样例在程序最下面。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#define N 300005using namespace std;int n,m,Q,cnt,dfn,top,eul;int fa[N][20];int a[N],b[N],f[N],stack[N],point[N],rem[N],belong[N],deep[N],head[N],id[N],size[N],pos[N];int next[N<<1],list[N<<1];pair<int,int> ss[N<<1],st[N<<1][21];inline int read(){    int a=0,f=1; char c=getchar();    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}    return a*f;}inline void insert(int x,int y){    next[++cnt]=head[x];    head[x]=cnt;    list[cnt]=y;}void dfs(int x){    id[x]=++dfn; size[x]=1; ss[++eul]=make_pair(deep[x],x); pos[x]=eul;    for (int i=1;(1<<i)<=deep[x];i++)        fa[x][i]=fa[fa[x][i-1]][i-1];    for (int i=head[x];i;i=next[i])        if (list[i]!=fa[x][0])        {            fa[list[i]][0]=x;            deep[list[i]]=deep[x]+1;            dfs(list[i]);            size[x]+=size[list[i]];            ss[++eul]=make_pair(deep[x],x);        }}inline void make_st(){    for (int i=1;i<=eul;i++) st[i][0]=ss[i];    for (int j=1;j<=20;j++)        for (int i=1;i<=eul;i++)            if (i+(1<<j)-1<=eul)                st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);}inline int lca(int x,int y){    int l=pos[x],r=pos[y];    if (l>r) swap(l,r);    int k=log2(r-l+1);    pair<int,int> ans=min(st[l][k],st[r-(1<<k)+1][k]);    return ans.second;}inline bool cmp(int a,int b){    return id[a]<id[b];}inline int dis(int x,int y){    return deep[x]+deep[y]-(deep[lca(x,y)]<<1);}void dp1(int x){    point[++dfn]=x; rem[x]=size[x];     for (int i=head[x];i;i=next[i])    {        dp1(list[i]);        if (!belong[list[i]]) continue;        int t1=dis(belong[list[i]],x),t2=dis(belong[x],x);        if (t1<t2||!belong[x]||(t1==t2&&belong[list[i]]<belong[x]))            belong[x]=belong[list[i]];    }}void dp2(int x){    for (int i=head[x];i;i=next[i])    {        int t1=dis(belong[x],list[i]),t2=dis(belong[list[i]],list[i]);        if (t1<t2||!belong[list[i]]||(t1==t2&&belong[x]<belong[list[i]]))            belong[list[i]]=belong[x];        dp2(list[i]);    }}void solve(int a,int b){    int x=b,mid=b;    for (int i=18;~i;i--)        if (deep[fa[x][i]]>deep[a])             x=fa[x][i];    rem[a]-=size[x];    if (belong[a]==belong[b])    {        f[belong[a]]+=size[x]-size[b];        return;    }    for (int i=18;~i;i--)    {        if (deep[fa[mid][i]]<=deep[a]) continue;        int t=fa[mid][i];        int t1=dis(belong[a],t),t2=dis(t,belong[b]);        if (t1>t2||(t1==t2&&belong[a]>belong[b])) mid=t;    }    f[belong[a]]+=size[x]-size[mid];    f[belong[b]]+=size[mid]-size[b];}inline void query(){    m=read();    for (int i=1;i<=m;i++) a[i]=b[i]=read();    for (int i=1;i<=m;i++) belong[a[i]]=a[i];    sort(a+1,a+m+1,cmp);    top=0; dfn=0; cnt=0;    if (belong[1]!=1) stack[++top]=1;    for (int i=1;i<=m;i++)    {        int t=a[i],f;        while (top)        {            f=lca(stack[top],t);            if (top>1&&deep[f]<deep[stack[top-1]])                 insert(stack[top-1],stack[top]),top--;            else if (deep[f]<deep[stack[top]])             {                insert(f,stack[top]);                top--;                break;            }            else break;        }        if (stack[top]!=f) stack[++top]=f; stack[++top]=t;    }    while (top>1) insert(stack[top-1],stack[top]),top--;    dp1(1); dp2(1);    for (int i=1;i<=dfn;i++)        for (int j=head[point[i]];j;j=next[j])            solve(point[i],list[j]);    for (int i=1;i<=dfn;i++)         f[belong[point[i]]]+=rem[point[i]];    for (int i=1;i<=m;i++)         printf("%d ",f[b[i]]);     puts("");    for (int i=1;i<=dfn;i++)        head[point[i]]=rem[point[i]]=belong[point[i]]=f[point[i]]=0;}int main(){    n=read();    for (int i=1;i<n;i++)    {        int u=read(),v=read();        insert(u,v); insert(v,u);    }    dfs(1);    make_st();    memset(head,0,sizeof(head));     Q=read();    while (Q--) query();    return 0;}/*102 13 24 35 46 17 38 39 410 1526 152 7 3 6 91848 7 10 352 9 3 5 81 9 3 1 4 1 1 10 1 1 3 5 4 1 3 1 1 */
0 0
原创粉丝点击