POJ 2763 Housewife Wind

来源:互联网 发布:知乎查看自己的匿名 编辑:程序博客网 时间:2024/05/17 20:32

传送门

题目大意:给定一棵树,支持修改边权和查询两点距离。

显然可以链剖去做。但是注意到dis(x,y)=dis(1,x)+dis(1,y)-2*(dis(1,LCA(x,y)))。

然后修改到x的边的边权等价于让x子树中的所有点的dis(1,y)+=c。

然后显然可以用BIT维护。

#include<iostream>#include<cstring>#include<cstdio>#include<queue>#define MAXN 100010#define MAXM 200010#define MAXL 21#define lowbit(x) ((x)&(-(x)))using namespace std;struct edges{int to,pre,wgt,id;}e[MAXM];int out[MAXN];int to[MAXN],h[MAXN],etop,d[MAXN];int in[MAXN],times[MAXN],dfs_clock;int up[MAXN][MAXL],dep[MAXN],w[MAXN];int add_edge(int u,int v,int w,int id){etop++;e[etop].to=v;e[etop].wgt=w;e[etop].id=id;e[etop].pre=h[u];h[u]=etop;return 0;}int dfs(int x,int f,int dis,int id){times[in[x]=++dfs_clock]=x;d[x]=dis;up[x][0]=f;dep[x]=dep[f]+1;to[id]=x;for(int i=1;i<MAXL;i++)up[x][i]=up[up[x][i-1]][i-1];for(int i=h[x];i;i=e[i].pre)if(e[i].to^f) dfs(e[i].to,x,dis+e[i].wgt,e[i].id);out[x]=dfs_clock;return 0;}inline int getLCA(int u,int v){if(dep[u]<dep[v]) swap(u,v);for(int i=MAXL-1;i>=0;i--)if(dep[up[u][i]]>=dep[v])u=up[u][i];if(u==v) return u;for(int i=MAXL-1;i>=0;i--)if(up[u][i]!=up[v][i])u=up[u][i],v=up[v][i];return up[u][0];}struct segment{int l,r,s,pt;segment *ch[2];}*rt,seg_pool[MAXN<<1];queue<segment*> pool;inline int push_up(segment* &rt){return rt->s=rt->ch[0]->s+rt->ch[1]->s;}inline int update_tags(segment* &rt,int v){rt->pt+=v;rt->s+=(rt->r-rt->l+1)*v;return 0;}inline int push_down(segment* &rt){update_tags(rt->ch[0],rt->pt);update_tags(rt->ch[1],rt->pt);return rt->pt=0;}inline int build(segment* &rt,int l,int r){//rt=pool.front();pool.pop();rt=new segment;rt->l=l,rt->r=r;rt->ch[0]=rt->ch[1]=NULL;rt->s=rt->pt=0;if(l==r) return rt->s=d[times[l]];int mid=(l+r)>>1;build(rt->ch[0],l,mid);build(rt->ch[1],mid+1,r);push_up(rt);return 0;}inline int update(segment* &rt,int s,int t,int v){int l=rt->l,r=rt->r;if(s<=l&&r<=t) return update_tags(rt,v);if(rt->pt) push_down(rt);int mid=(l+r)>>1;if(s<=mid) update(rt->ch[0],s,t,v);if(mid<t) update(rt->ch[1],s,t,v);return push_up(rt);}inline int query(segment* &rt,int p){int l=rt->l,r=rt->r;if(l==r) return rt->s;if(rt->pt) push_down(rt);int mid=(l+r)>>1;if(p<=mid) return query(rt->ch[0],p);else return query(rt->ch[1],p);}inline int delseg(segment* &rt){if(rt==NULL) return 0;delseg(rt->ch[0]);delseg(rt->ch[1]);pool.push(rt);rt=NULL;return 0;}int v[MAXN],n;inline int update(int x,int val){for(x;x<=n;x+=lowbit(x))v[x]+=val;return 0;}inline int query(int x){int ans=0;for(x;x;x-=lowbit(x))ans+=v[x];return ans;}int main(){int q,x;//for(int i=0;i<(MAXN<<1);i++) pool.push(&seg_pool[i]);while(scanf("%d%d%d",&n,&q,&x)!=EOF&&(n||q||x)){memset(h,0,sizeof(h));etop=0;for(int i=1;i<n;i++){int u,v;scanf("%d%d%d",&u,&v,&w[i]);add_edge(u,v,w[i],i);add_edge(v,u,w[i],i);}dfs_clock=0;int root=1;dfs(root,0,0,0);//build(rt,1,n);memset(v,0,sizeof(v));for(int i=1;i<=n;i++) update(i,d[times[i]]-d[times[i-1]]);while(q--){int opt;scanf("%d",&opt);if(!opt){int y;scanf("%d",&y);//printf("%d\n",query(rt,in[x])+query(rt,in[y])-(query(rt,in[getLCA(x,y)])<<1));printf("%d\n",query(in[x])+query(in[y])-(query(in[getLCA(x,y)])<<1));x=y;}else{int id,c;scanf("%d%d",&id,&c);//update(rt,in[to[id]],out[to[id]],c-w[id]);w[id]=c;update(in[to[id]],c-w[id]);update(out[to[id]]+1,w[id]-c);w[id]=c;}}//delseg(rt);}return 0;}


原创粉丝点击