您的位置:首页 > 理论基础 > 计算机网络

hdu 4757 Tree 南京网络赛 1010

2013-10-07 13:00 323 查看
可持久化字典树,每个节点存一棵根节点到它的节点构成的字典树,利用父节点的信息来构树。查询的时候通过最近公共祖先,查询的两个点,三个点的共同信息可以得到两点路径除公共祖先外的点构成的字典树的情况,从而得出最优解。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=1e5+9,maxm=2e6;
int a[maxn],f[maxn];
int n,m;
bool visit[maxn];
struct
{
int from,to,w,fa;
}qry[maxn];
struct ED
{
int head[maxn],lon;
struct
{
int next,to,from,id;
}e[maxn<<1];
void clear()
{
memset(head,-1,sizeof(head));
lon=0;
}
void add(int from,int to,int id=0)
{
e[++lon].to=to;
e[lon].from=from;
e[lon].next=head[from];
e[lon].id=id;
head[from]=lon;
}
}edge[2];

struct T
{
int lon,root[maxn];
struct
{
int to[2],son;
}node[maxm];
void clear()
{
root[0]=lon=0;
for(int i=0;lon<150000;i++)
{
node[i].to[0]=++lon;
node[i].to[1]=++lon;
node[i].son=0;
}
}
void insert(int t,int now)
{
int r=root[t];
node[++lon]=node[r];
r=root[now]=lon;
for(int i=16;i>=0;i--)
{
int u=(1<<i&a[now])>0;
node[++lon]=node[node[r].to[u]];
r=node[r].to[u]=lon;
node[r].son++;
}
}
}tr;

int find(int x)
{
if(f[x]!=x)  f[x]=find(f[x]);
return f[x];
}

void merge(int a,int b)
{
f[find(b)]=find(a);
}

void dfs(int t,int from)
{
visit[t]=1;
for(int k=edge[1].head[t];k!=-1;k=edge[1].e[k].next)
{
int u=edge[1].e[k].to;
int id=edge[1].e[k].id;
if(visit[u])
qry[id].fa=find(u);
}

for(int k=edge[0].head[t];k!=-1;k=edge[0].e[k].next)
{
int u=edge[0].e[k].to;
if(u==from) continue;
dfs(u,t);
}
merge(from,t);
}

void getlca()
{
memset(visit,0,sizeof(visit));
for(int i=1;i<=n;i++)
f[i]=i;
dfs(1,0);
}

void built(int t,int from)
{
for(int k=edge[0].head[t];k!=-1;k=edge[0].e[k].next)
{
int u=edge[0].e[k].to;
if(u==from) continue;
tr.insert(t,u);
built(u,t);
}
}

inline int get(int r,int u)
{
return tr.node[tr.node[r].to[u]].son;
}

int ask(int t)
{
int ans=0;
int s1=qry[t].from,s2=qry[t].to,s3=qry[t].fa,w=qry[t].w;
int r1=tr.root[s1],r2=tr.root[s2],r3=tr.root[s3];
for(int i=16;i>=0;i--)
{
int u=(1<<i&w)>0;
u^=1;
if(get(r1,u)+(get(r2,u))>get(r3,u)*2) ans+=(1<<i);
else u^=1;
r1=tr.node[r1].to[u];
r2=tr.node[r2].to[u];
r3=tr.node[r3].to[u];
}
ans=max(ans,a[s3]^w);
return ans;
}

void solve()
{
for(int i=1;i<=m;i++)
{
cout<<ask(i)<<endl;;
}
}

int main()
{
//    freopen("in.txt","r",stdin);
while(scanf("%d %d",&n,&m)!=EOF)
{
edge[0].clear();
edge[1].clear();
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1,from,to;i<n;i++)
{
scanf("%d %d",&from,&to);
edge[0].add(from,to);
edge[0].add(to,from);
}
for(int i=1,from,to,w;i<=m;i++)
{
scanf("%d %d %d",&from,&to,&w);
qry[i].from=from;
qry[i].to=to;
qry[i].w=w;
edge[1].add(from,to,i);
edge[1].add(to,from,i);
}
getlca();
tr.clear();
edge[0].add(0,1);
built(0,-1);
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: