您的位置:首页 > Web前端

poj 2763 Housewife Wind 动态求树上两点之间距离

2015-10-13 14:52 429 查看
题意:

给一棵n<100000个节点的树,和q<100000个操作,每个操作可以将一条边的权改变或者查询树中两点之间的距离。

分析:

首先用dfs将树序列化,然后用rmq求lca,用树状数组求树上两点之间的距离和更新边。

 代码:

//poj 2763
//sep9
#include <iostream>
#include <cmath>
using namespace std;
const int MAXN=100024;
const int LOG_MAXN=20;
struct EDGE{
int idx,v,w,nxt;
}edge[MAXN*2];

struct BIT
{
int c[MAXN*2],n;
void clear(){
memset(c,0,sizeof(c));
}
int lowbit(int x){
return x&(x^(x-1));
}
void modify(int i,int d){
while(i<=n){
c[i]+=d;
i+=lowbit(i);
}
}
int q(int i){
if(i==0) return 0;
int sum;
for(sum=0;i>0;i-=lowbit(i))
sum+=c[i];
return sum;
}
}bit;

int n,q,s,e;
int head[MAXN];

int vs[MAXN*2];
int depth[MAXN*2];
int idx[MAXN];
int es[MAXN*2];
int dis[MAXN*2];
int ST[MAXN*2][LOG_MAXN],ST_IDX[MAXN*2][LOG_MAXN];

void dfs(int u,int p,int d,int &k)
{
idx[u]=k;
vs[k]=u;
depth[k++]=d;
for(int i=head[u];i!=-1;i=edge[i].nxt){
int v=edge[i].v;
if(v!=p){
bit.modify(k,edge[i].w);
dis[edge[i].idx*2]=edge[i].w;
es[edge[i].idx*2]=k;
dfs(v,u,d+1,k);
vs[k]=u;
depth[k]=d;
bit.modify(k,-edge[i].w);
es[edge[i].idx*2+1]=k++;
}
}
}

void rmq_init(int a[],int lenth)
{
for(int i=0;i<lenth;++i){
ST[i][0]=a[i];
ST_IDX[i][0]=i;
}
for(int j=1;(1<<j)<=lenth;++j)
for(int i=0;i+(1<<j)<=lenth;++i){
ST[i][j]=ST[i][j-1];
ST_IDX[i][j]=ST_IDX[i][j-1];
if(ST[i+(1<<(j-1))][j-1]<ST[i][j]){
ST[i][j]=ST[i+(1<<(j-1))][j-1];
ST_IDX[i][j]=ST_IDX[i+(1<<(j-1))][j-1];
}
}
}

int query(int l,int r)//[]
{
int k=(int)(log(r-l+1.0)/log(2.0));
if(ST[l][k]<=ST[r-(1<<k)+1][k])
return ST_IDX[l][k];
return ST_IDX[r-(1<<k)+1][k];
}

void init()
{
bit.clear();
bit.n=2*n;
int k=0;
dfs(1,-1,0,k);
rmq_init(depth,2*n-1);
}

int lca(int a,int b)
{
return vs[query(min(idx[a],idx[b]),max(idx[a],idx[b]))];
}

int main()
{
scanf("%d%d%d",&n,&q,&s);
e=0;
memset(head,-1,sizeof(head));
for(int i=0;i<n-1;++i){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
edge[e].idx=i,edge[e].v=v,edge[e].w=w,edge[e].nxt=head[u],head[u]=e++;
edge[e].idx=i,edge[e].v=u,edge[e].w=w,edge[e].nxt=head[v],head[v]=e++;
}
init();
while(q--){
int type;
scanf("%d",&type);
if(type==0){
int x;
scanf("%d",&x);
int p=lca(s,x);
printf("%d\n",bit.q(idx[s])+bit.q(idx[x])-2*bit.q(idx[p]));
s=x;
}else{
int x,y;
scanf("%d%d",&x,&y);
int k=x-1;
bit.modify(es[k*2],y-dis[k*2]);
bit.modify(es[k*2+1],dis[k*2]-y);
dis[k*2]=y;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj 算法