POJ-2763-Housewife Wind(LCA+dfs序線段樹)
阿新 • • 發佈:2019-02-13
有邊權修改的樹中兩點距離查詢。
因為有邊權修改,所以用線段樹維護到根的序列。
LCA求距離。
這題有個坑點就是不能用vector
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=1e5+7;
int a[maxn],d[maxn],deep[maxn],len[maxn],lz[maxn<<2],f[maxn],anc[maxn][20];
int head[maxn];
int n,m,h,tot;
struct Edge
{
int u,v,d,next;
Edge(){}
Edge(int _v,int _d):v(_v),d(_d){}
Edge(int _u,int _v,int _d):u(_u),v(_v),d(_d){}
};
Edge e[maxn<<1];
int dfs(int u,int pre,int deep,int dis)
{
anc[u][0]=pre;
a[++m]=u;
f[u]=m;
::deep[u]=deep;
d[u]=dis;
int cnt=1;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].v;
if(v==pre) continue;
cnt+=dfs(v,u,deep+1,dis+e[i].d);
}
return len[u]=cnt;
}
inline void push_down(int rt)
{
if(!lz[rt]) return;
lz[rt<<1]+=lz[rt];
lz[rt<<1|1]+=lz[rt];
lz[rt]=0;
}
void update(int rt,int l,int r,int ql,int qr,int val)
{
if(l>=ql&&r<=qr)
{
lz[rt]+=val;
return ;
}
push_down(rt);
int mid=(l+r)>>1;
if(ql<=mid) update(rt<<1,l,mid,ql,qr,val);
if(qr>mid) update(rt<<1|1,mid+1,r,ql,qr,val);
}
void query(int rt,int l,int r,int p)
{
if(l==r)
{
d[a[p]]+=lz[rt];
lz[rt]=0;
return ;
}
push_down(rt);
int mid=(l+r)>>1;
if(p<=mid) query(rt<<1,l,mid,p);
else query(rt<<1|1,mid+1,r,p);
}
inline void init()
{
for(int j=1;(1<<j)<n;j++)
{
h=j;
for(int i=1;i<=n;i++)
anc[i][j]=anc[i][j-1]==-1?-1:anc[anc[i][j-1]][j-1];
}
}
inline int lca(int u,int v)
{
if(deep[u]<deep[v]) swap(u,v);
for(int j=h;j>=0;j--)
if(deep[u]-(1<<j)>=deep[v])
u=anc[u][j];
if(u==v) return u;
for(int j=h;j>=0;j--)
if(anc[u][j]!=anc[v][j])
u=anc[u][j],v=anc[v][j];
return anc[u][0];
}
inline void addedge(int u, int v, int c)
{
e[tot].u=u;e[tot].v=v;e[tot].d=c;
e[tot].next=head[u];
head[u]=tot;
++tot;
}
int main()
{
int q,s;
while(~scanf("%d%d%d",&n,&q,&s))
{
m=0;
int u,v,c,op,rid;
tot=0;
memset(head,-1,sizeof(head));
memset(lz,0,sizeof(int)*((n+3)<<2));
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&u,&v,&c);
addedge(u,v,c);
addedge(v,u,c);
}
dfs(1,-1,1,0);
init();
while(q--)
{
scanf("%d",&op);
if(op)
{
scanf("%d%d",&rid,&c);
rid=(rid-1)<<1;
u=e[rid].u;v=e[rid].v;
if(deep[u]<deep[v]) swap(u,v);
if(f[u]<0||f[u]+len[u]-1>n) return 0;
update(1,1,n,f[u],f[u]+len[u]-1,c-e[rid].d);
e[rid].d=e[rid^1].d=c;
}
else
{
scanf("%d",&v);
u=s;
int fa=lca(u,v);
query(1,1,n,f[u]);
query(1,1,n,f[v]);
query(1,1,n,f[fa]);
printf("%d\n",d[u]+d[v]-2*d[fa]);
s=v;
}
}
}
return 0;
}