题意:

给你n个点和n-1条边组成的一棵树,按顺序给出数的每一条边。

询问m次,每次给出一个x求x除以从点a到点b所有边的权值和的乘积,还有修改,给出边的编号,修改某条边的权值。

思路:

树链剖分,用点的编号建立线段树,当然一开始要记录第几条边的两个端点各是什么,便于修改的时候进行查询。

重点是用深度较大的那个点记录两个点之间的权值。

查询的时候当两者重链的top相等的时候注意去掉top点的权值。

然后这道题每条边的权值都是在10^18以内,所以如果线段树某个元素代表的权值之乘积大于1e18的话就直接标记成0或者别的。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n,m;
long long ttmp[];
long long INF=1e18;
struct bian
{
int a,b;
long long c;
};
bian bians[];
struct edge
{
int id;
long long num;
edge *next;
};
edge edges[<<];
edge *adj[];
int ednum;
inline void addEdge(int a,int b,long long c)
{
edge *tmp;
tmp=&edges[ednum++];
tmp->id=b;
tmp->num=c;
tmp->next=adj[a];
adj[a]=tmp;
}
int fa[],top[],son[],siz[],id[],fid[],dep[];
bool vis[];
void dfs1(int me,int deep)
{
int maxsiz=-;
vis[me]=;
dep[me]=deep;
siz[me]=;
for(edge *it=adj[me];it;it=it->next)
{
if(!vis[it->id])
{
fa[it->id]=me;
dfs1(it->id,deep+);
if(maxsiz<siz[it->id])
{
maxsiz=siz[it->id];
son[me]=it->id;
}
siz[me]+=siz[it->id];
}
}
}
int num;
void dfs2(int me,int t)
{
vis[me]=;
top[me]=t;
id[me]=++num;
fid[num]=me;
if(son[me])
{
dfs2(son[me],t);
}
for(edge *it=adj[me];it;it=it->next)
{
if(!vis[it->id])
{
dfs2(it->id,it->id);
}
}
}
struct tr
{
int s,e;
long long num;
};
tr tree[<<];
long long mul(long long aaa,long long bbb)
{
if(aaa==||bbb==)
return ;
if(INF/aaa<bbb)
{
return ;
}
else
return aaa*bbb;
}
void build(int k,int s,int e)
{
tree[k].s=s;
tree[k].e=e;
if(s==e)
{
tree[k].num=ttmp[fid[s]];
return;
}
int mid=(s+e)>>;
build(k<<,s,mid);
build(k<<|,mid+,e);
tree[k].num=mul(tree[k<<].num,tree[k<<|].num);
}
long long ans;
void qsum(int k,int s,int e)
{
if(tree[k].s==s&&tree[k].e==e)
{
if(fid[s]==)
return;
ans=mul(ans,tree[k].num);
return;
}
int mid=(tree[k].s+tree[k].e)>>;
if(e<=mid)
{
qsum(k<<,s,e);
}
else if(s>mid)
{
qsum(k<<|,s,e);
}
else
{
qsum(k<<,s,mid);
qsum(k<<|,mid+,e);
}
} inline void print(int a,int b,long long c)
{
ans=;
int f1=top[a],f2=top[b];
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(f1,f2);
swap(a,b);
}
qsum(,id[f1],id[a]);
a=fa[f1];
f1=top[a];
}
if(dep[a]>dep[b])
{
swap(a,b);
}
if(id[a]+<=id[b])
{
qsum(,id[a]+,id[b]);
}
if(ans==)
printf("0\n");
else
printf("%I64d\n",c/ans);
}
void updat(int k,int tar,long long c)
{
if(tree[k].s==tree[k].e)
{
tree[k].num=c;
return;
}
int mid=(tree[k].s+tree[k].e)>>;
if(tar<=mid)
{
updat(k<<,tar,c);
}
else
{
updat(k<<|,tar,c);
}
tree[k].num=mul(tree[k<<].num,tree[k<<|].num);
}
int main()
{
num=;
memset(vis,,sizeof(vis));
memset(son,,sizeof(son));
ednum=;
scanf("%d%d",&n,&m);
for(int i=;i<n;i++)
{
int a,b;
scanf("%d%d%I64d",&a,&b,&bians[i].c);
bians[i].a=a;
bians[i].b=b;
addEdge(a,b,bians[i].c);
addEdge(b,a,bians[i].c);
}
fa[]=;
dfs1(,);
memset(vis,,sizeof(vis));
dfs2(,);
for(int i=;i<n;i++)
{
if(dep[bians[i].a]>dep[bians[i].b])
{
ttmp[bians[i].a]=bians[i].c;
}
else
{
ttmp[bians[i].b]=bians[i].c;
}
}
build(,,n);
for(int i=;i<=m;i++)
{
int typ,a,b;
long long c;
scanf("%d",&typ);
if(typ==)
{
scanf("%d%d%I64d",&a,&b,&c);
print(a,b,c);
}
else
{
scanf("%d%I64d",&a,&c);
if(dep[bians[a].a]<dep[bians[a].b])
{
updat(,id[bians[a].b],c);
}
else
{
updat(,id[bians[a].a],c);
}
}
}
}

CodeForces 593D【树链剖分】的更多相关文章

  1. Water Tree CodeForces 343D 树链剖分+线段树

    Water Tree CodeForces 343D 树链剖分+线段树 题意 给定一棵n个n-1条边的树,起初所有节点权值为0. 然后m个操作, 1 x:把x为根的子树的点的权值修改为1: 2 x:把 ...

  2. Codeforces Round #425 (Div. 2) Problem D Misha, Grisha and Underground (Codeforces 832D) - 树链剖分 - 树状数组

    Misha and Grisha are funny boys, so they like to use new underground. The underground has n stations ...

  3. CodeForces - 343D 树链剖分

    题目链接:http://codeforces.com/problemset/problem/343/D 题意:给定一棵n个n-1条边的树,起初所有节点权值为0,然后m个操作. 1 x:把x为根的子树的 ...

  4. CodeForces 191C 树链剖分 第4遍

    非常无奈,模板重新无奈的打错了.. 只是,非常快便找到了.. 题意:给一些边,有一些操作,每次操作,都要在这些边上加上1,求每一个边的边权.. #include<cstdio> #incl ...

  5. D. Happy Tree Party CodeForces 593D【树链剖分,树边权转点权】

    Codeforces Round #329 (Div. 2) D. Happy Tree Party time limit per test 3 seconds memory limit per te ...

  6. Educational Codeforces Round 3 E. Minimum spanning tree for each edge (最小生成树+树链剖分)

    题目链接:http://codeforces.com/contest/609/problem/E 给你n个点,m条边. 问枚举每条边,问你加这条边的前提下组成生成树的权值最小的树的权值和是多少. 先求 ...

  7. Codeforces Round #329 (Div. 2) D. Happy Tree Party 树链剖分

    D. Happy Tree Party Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/593/p ...

  8. 【Codeforces】【网络流】【树链剖分】【线段树】ALT (CodeForces - 786E)

    题意 现在有m个人,每一个人都特别喜欢狗.另外还有一棵n个节点的树. 现在每个人都想要从树上的某个节点走到另外一个节点,且满足要么这个人自带一条狗m,要么他经过的所有边h上都有一条狗. 2<=n ...

  9. Codeforces 704E Iron Man [树链剖分,计算几何]

    Codeforces 这题--真是搞死我了-- 好不容易下定了决心要不颓废,要写题,结果一调就调了十几个小时-- 思路 我们发现在树上做非常不舒服,于是树链剖分之后一次在重链上的移动就可以看做是在df ...

随机推荐

  1. pentaho kettle svn

    svn://source.pentaho.org/svnkettleroot/big data : svn://source.pentaho.org/svnkettleroot/archive/pen ...

  2. 从MySQL到Redis 提升数据迁移的效率

    场景是从MySQL中将数据导入到Redis的Hash结构中.当然,最直接的做法就是遍历MySQL数据,一条一条写入到Redis中.这样可能没什么错,但是速度会非常慢.而如果能够使MySQL的查询输出数 ...

  3. hadoop(二):hdfs HA原理及安装

    早期的hadoop版本,NN是HDFS集群的单点故障点,每一个集群只有一个NN,如果这个机器或进程不可用,整个集群就无法使用.为了解决这个问题,出现了一堆针对HDFS HA的解决方案(如:Linux ...

  4. ettercap ARP dns 欺骗

    1.arp 这个简单,太熟了.略过1     2.dns   根据arp欺骗的步骤. 多了个etter.dns文件 找到它:locate etter.dns 进入后添加dns正向解析     启动,选 ...

  5. 【转】8张图理解Java

    一图胜千言,下面图解均来自Program Creek 网站的Java教程,目前它们拥有最多的票选.如果图解没有阐明问题,那么你可以借助它的标题来一窥究竟. 1.字符串不变性 下面这张图展示了这段代码做 ...

  6. php提高效率

    1. foreach效率更高,尽量用foreach代替while和for循环. 2. 循环内部不要声明变量,尤其是对象这样的变量. 3. 在多重嵌套循环中,如有可能,应当将最长的循环放在内层,最短循环 ...

  7. C语言中字符串常量到底存在哪了?

    常量存储总结局部变量.静态局部变量.全局变量.全局静态变量.字符串常量以及动态申请的内存区 1.局部变量存储在栈中2.全局变量.静态变量(全局和局部静态变量)存储在静态存储区3.new申请的内存是在堆 ...

  8. TMS320C54x系列DSP的CPU与外设——第3章 存储器

    第3章  存储器 本章介绍了TMS320C54x DSP存储器的构成和操作.一般来说,C54x器件共有192K 16位字的存储窨,这个空间分成3个专用的部分:64K字程序.64K字数据和64K字I/O ...

  9. MySQL key/value存储方案(转)

    需求 250M entities, entities表共有2.5亿条记录,当然是分库的. 典型解决方案:RDBMS 问题:由于业务需要不定期更改表结构,但是在2.5亿记录的表上增删字段.修改索引需要锁 ...

  10. Tomcat插件与Jetty插件在MyEclipse中的配置

    -Djetty.port=8101 jetty:run tomcat6:run <plugin> <groupId>org.apache.tomcat.maven</gr ...