POJ2763 Housewife Wind (树链剖分)
作者:互联网
差不多是模板题,不过要注意将边权转化为点权,将边的权值赋给它所连的深度较大的点。
这样操作过后,注意查询ask()的代码有所改变(见代码注释)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=100010; 6 int head[maxn],to[maxn<<1],nxt[maxn<<1],tot,cnt; 7 int fa[maxn],dep[maxn]; 8 int size[maxn],son[maxn],top[maxn]; 9 int id[maxn],rev[maxn]; 10 int Sum; 11 12 struct edge{ 13 int u,v,w; 14 }a[maxn]; 15 16 struct node{ 17 int l,r,sum; 18 }tree[maxn<<2]; 19 20 void add(int u,int v){ 21 nxt[++tot]=head[u]; 22 head[u]=tot; 23 to[tot]=v; 24 } 25 26 void init(){ 27 tot=cnt=0; 28 memset(head,0,sizeof(head)); 29 memset(son,0,sizeof(son)); 30 } 31 32 void dfs1(int u,int f){ 33 size[u]=1,fa[u]=f,dep[u]=dep[f]+1; 34 for(int i=head[u];i;i=nxt[i]){ 35 int v=to[i]; 36 if(v==f) continue; 37 dfs1(v,u); 38 size[u]+=size[v]; 39 if(size[v]>size[son[u]]) son[u]=v; 40 } 41 } 42 43 void dfs2(int u,int t){ 44 top[u]=t; 45 id[u]=++cnt; 46 rev[cnt]=u; 47 if(!son[u]) return ; 48 dfs2(son[u],t); 49 for(int i=head[u];i;i=nxt[i]){ 50 int v=to[i]; 51 if(v!=fa[u] && v!=son[u]) dfs2(v,v); 52 } 53 } 54 55 void pushup(int k){ 56 tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum; 57 } 58 59 void build(int k,int l,int r){ 60 tree[k].l=l;tree[k].r=r; 61 if(l==r) return ; 62 int mid=(l+r)>>1; 63 build(k<<1,l,mid); 64 build(k<<1|1,mid+1,r); 65 } 66 67 void change(int k,int x,int y){ 68 if(tree[k].l==tree[k].r && tree[k].l==x){ 69 tree[k].sum=y; 70 return ; 71 } 72 int mid=(tree[k].l+tree[k].r)>>1; 73 if(x<=mid) change(k<<1,x,y); 74 else change(k<<1|1,x,y); 75 pushup(k); 76 } 77 78 void query(int k,int l,int r){//查询线段树中[l,r]的和值 79 if(tree[k].l>=l && tree[k].r<=r){//找到该区间 80 Sum+=tree[k].sum; 81 return; 82 } 83 int mid=(tree[k].l+tree[k].r)>>1; 84 if(l<=mid) query(k<<1,l,r); 85 if(r>mid) query(k<<1|1,l,r); 86 } 87 88 void ask(int u,int v){ 89 while(top[u]!=top[v]){ 90 if(dep[top[u]]<dep[top[v]]) swap(u,v); 91 query(1,id[top[u]],id[u]);//这里是top,下面是son,可以画图模拟一下,验证其正确性 92 u=fa[top[u]]; 93 } 94 if(u==v) return ;//边权化为点权,加上这一步很有必要,防止重复算 95 if(dep[u]>dep[v]) swap(u,v); 96 query(1,id[son[u]],id[v]);//注意是son[u] 97 } 98 99 int main(){ 100 int n,q,s; 101 init(); 102 scanf("%d%d%d",&n,&q,&s); 103 for(int i=1;i<n;i++){ 104 scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w); 105 add(a[i].u,a[i].v); add(a[i].v,a[i].u); 106 } 107 dfs1(1,0); 108 dfs2(1,1); 109 build(1,1,cnt);//创建线段树 110 for(int i=1;i<n;i++){//边权转化为点权 111 if(dep[a[i].u]>dep[a[i].v]) 112 swap(a[i].u,a[i].v); 113 change(1,id[a[i].v],a[i].w); 114 } 115 int opt,i,val,x; 116 while(q--){ 117 scanf("%d",&opt); 118 if(opt){ 119 scanf("%d%d",&i,&val); 120 change(1,id[a[i].v],val);//改变第i条边的值为val 121 } 122 else{ 123 scanf("%d",&x); 124 Sum=0; 125 ask(s,x);//查询s->x路径上边权的和值 126 printf("%d\n",Sum); 127 s=x;//更新温迪的位置 128 } 129 } 130 return 0; 131 }
标签:val,剖分,int,scanf,d%,son,POJ2763,id,Wind 来源: https://www.cnblogs.com/yhxnoerror/p/16435853.html