codeforces #329 D. Happy Tree Party (LCA+并查集 || 树链剖分)

来源:互联网 发布:pid补偿网络 编辑:程序博客网 时间:2024/06/07 06:44

题目:http://codeforces.com/contest/593/problem/D

题意:给定一棵n个节点的树。有两种操作:①给定 u v p, 求p除u--->v这条链上所有的边权的值(每次上下取整)②修改某一条边的边权。

分析:

解法一:由于p<=10^18,所以p最多除以60个大于等于2的数就会变为0,当我们遍历一条链的时候只要能避开那些边权为1的边就行了。为每个节点添加一个索引,指向第一个不为1的祖先。初始的时候每个节点的索引指向父亲节点,每次查询的时候顺便压缩一下路径就行了。

具体做法:u-->lca (deep(u)>deep(lca)), v-->lca (deep(v)>deep(lca))

代码:

#include <bits/stdc++.h>using namespace std;typedef long long LL;const LL INF = 1E9+9;const int maxn = 4e5+6;struct node{int v,next;LL w;}List[maxn];int head[maxn],cnt;void add(int u,int v,LL w){List[cnt].v=v;List[cnt].w=w;List[cnt].next=head[u];head[u]=cnt++;}int anc[200009][20],deep[200009],index[200009];LL fw[maxn];void dfs(int cur,int dp){deep[cur]=dp;for(int i=head[cur];~i;i=List[i].next){int son=List[i].v;if(anc[cur][0]!=son){anc[son][0]=cur;fw[son]=List[i].w;for(int j=1;j<20;j++)anc[son][j]=anc[anc[son][j-1]][j-1];dfs(son,dp+1);}}}int LCA(int a,int b){if(deep[a]<deep[b])swap(a,b);int h=deep[a]-deep[b];for(int i=0;i<20;i++)if((h>>i)&1)a=anc[a][i];if(a==b) return a;for(int i=19;i>=0;i--){if(anc[a][i]!=anc[b][i]){a=anc[a][i];b=anc[b][i];}}return anc[a][0];}pair <int,int> data[maxn];int main(){int n,q,i,j,k,u,v,x,y,tp;LL w,p;scanf("%d%d",&n,&q);memset(head,-1,sizeof(head));for(i=1;i<n;i++){scanf("%d%d%lld",&u,&v,&w);data[i]=make_pair(u,v);add(u,v,w);add(v,u,w);}for(i=1;i<=n;i++)anc[i][0]=1;dfs(1,0);for(int i=1;i<=n;i++)  //初始指向父亲节点 index[i]=anc[i][0];while(q--){scanf("%d",&tp);if(tp==1){scanf("%d%d%lld",&x,&y,&p);int lca=LCA(x,y);//printf("lca(%d %d):%d\n",x,y,lca);while(deep[x]>deep[lca] && p>0){p/=fw[x];x=(fw[index[x]]>1?index[x]:(index[x]=index[index[x]])); //路径压缩 }while(deep[y]>deep[lca] && p>0){p/=fw[y];y=(fw[index[y]]>1?index[y]:(index[y]=index[index[y]]));}printf("%lld\n",p);}else{scanf("%d%lld",&x,&p);u=data[x].first;v=data[x].second;if(anc[u][0]==v)swap(u,v);fw[v]=p; }}return 0;}

解法二:

floor(floor(x/n)/m)=floor(x/(nm))

直接树链剖分,用线段数维护区间乘积,注意溢出。

代码:

#include <bits/stdc++.h>using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1typedef long long LL;const LL INF = 1e18;const int maxn = 2e5+7;int head[maxn],cnt;struct node{int v,next;}List[maxn<<2];void add(int u,int v){List[cnt].v=v;List[cnt].next=head[u];head[u]=cnt++;}int top[maxn],deep[maxn],sz[maxn],fa[maxn],son[maxn],p[maxn],fp[maxn],pos;int dfs1(int cur,int dp){deep[cur]=dp;sz[cur]=1;son[cur]=-1;for(int i=head[cur];~i;i=List[i].next){int to=List[i].v;if(fa[cur]!=to){fa[to]=cur;sz[cur]+=dfs1(to,dp+1);if(son[cur]==-1 || sz[to]>sz[son[cur]])son[cur]=to; }}return sz[cur];}void dfs2(int cur,int sp){top[cur]=sp;p[cur]=pos++;fp[p[cur]]=cur;if(son[cur]==-1)return ;dfs2(son[cur],sp);for(int i=head[cur];~i;i=List[i].next){int to=List[i].v;if(to!=son[cur] && fa[cur]!=to)dfs2(to,to);}}LL tree[maxn<<2];LL Mul(LL a,LL b){if(a==0 || b==0 || INF/a<b)return 0;return a*b;}void update(int pos,LL v,int l,int r,int rt){if(l==r){tree[rt]=v;return ;}int m=(l+r)>>1;if(pos<=m)update(pos,v,lson);elseupdate(pos,v,rson);tree[rt]=Mul(tree[rt<<1],tree[rt<<1|1]);}LL query(int L,int R,int l,int r,int rt){if(L<=l && r<=R)return tree[rt];int m=(l+r)>>1;LL ret=1;if(L<=m)ret=Mul(ret,query(L,R,lson));if(R>m)ret=Mul(ret,query(L,R,rson));return ret;}LL Q(int L,int R){return query(L,R,1,pos,1);}LL solve(int u,int v){int f1=top[u],f2=top[v];LL ret=1;while(f1!=f2){if(deep[f1]<deep[f2]){swap(f1,f2);swap(u,v);}ret=Mul(ret,Q(p[f1],p[u]));if(!ret)return 0;u=fa[f1];f1=top[u];}if(u==v)return ret;if(deep[u]>deep[v])swap(u,v);return Mul(ret,Q(p[son[u]],p[v]));}LL in[maxn][3];int main(){int n,m,i,j,x,y;LL w;scanf("%d%d",&n,&m);memset(head,-1,sizeof(head));for(i=1;i<n;i++){scanf("%d%d%lld",&x,&y,&w);add(x,y);add(y,x);in[i][0]=x;in[i][1]=y;in[i][2]=w;}pos=1;dfs1(1,1);dfs2(1,1);for(i=1;i<n;i++){if(deep[in[i][0]]>deep[in[i][1]])swap(in[i][0],in[i][1]);update(p[in[i][1]],in[i][2],1,pos,1);}while(m--){int tp;LL val;scanf("%d",&tp);if(tp==1){scanf("%d%d%lld",&x,&y,&val);LL temp=solve(x,y);if(temp==0)puts("0");else printf("%lld\n",val/temp);}else{scanf("%d%lld",&x,&w);update(p[in[x][1]],w,1,pos,1);} }return 0;}

0 0
原创粉丝点击