ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

POJ2763 Housewife Wind (树链剖分)

2022-07-01 20:37:52  阅读:131  来源: 互联网

标签:val 剖分 int scanf d% son POJ2763 id 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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有