CSU 1663: Tree(树链剖分)
1663: Tree
Time Limit: 5 Sec Memory Limit: id=1663">Status pid=1663">Web
128 MB
Submit: 26 Solved: 11
[Submit][
Board
Description
CSU has a lot of trees. But there is a tree which is different from the others. This one is made of weighted edges and I have three kinds of operations on it:
1. C a b: Change the weight of edge a to b (1 ≤ b ≤ 100);
2. M a b c: Multiply the weights of those edges on the path from node a to node b by c (|c|≤10, c ≠ 0);
3. Q a b: Get the sum of weights from all the edges on the path from node a to node b.
Input
There are multiple test cases.
The first line will contain a positive integer T (T ≤ 10) meaning the number of test cases.
Each test case will have an integer N (1 ≤ N ≤ 50,000) indicating the number of nodes marked from 1 to N.
Then N-1 lines followed. Each lines contains three integers a, b and c (1 ≤ a, b, c ≤ N, a ≠ b, 1 ≤ c ≤ 100) indicating the there is an edge connecting node a and node b with weight c. The edges are marked from 1 to N-1 in the order of appearance.
Then some operations followed, with one operation per line. The format is as shown in the problem description. A single letter ‘E’ indicates the end of the case. There are no more than 50,000 operations per test case.
Output
For each ‘Q’ operation, output an integer meaning the sum. The final result will never exceed 32-bit signed integer.
Sample Input
2
4
1 2 14
1 3 20
3 4 1
C 3 11
M 1 4 3
M 3 4 2
M 1 3 2
Q 2 4
M 1 4 -1
M 3 4 -2
Q 2 4
E
3
1 2 4
1 3 2
Q 2 3
C 1 7
M 2 3 2
M 1 3 5
Q 2 3
E
Sample Output
200
26
6
34
#include<stdio.h>
#include<string.h>
#define LL long long
const int N = 50005; int head[N<<1],to[N<<1],next1[N<<1],tot;
int deep[N],fath[N],son[N],num[N];
int top[N],p[N],pos; void init(){
pos=tot=0;
memset(head,-1,sizeof(head));
}
void addEdge(const int& u, const int& v){
to[tot] = v, next1[tot] = head[u], head[u] = tot++;
}
void addUndirEdge(const int& u, const int& v){
addEdge(u, v), addEdge(v, u);
} void dfs1(int u,int pre,int d){
fath[u]=pre;
deep[u]=d;
son[u]=-1;
num[u]=1;
for(int i=head[u]; i!=-1; i=next1[i]){
int v=to[i];
if(v==fath[u])continue;
dfs1(v,u,d+1);
num[u]+=num[v];
if(son[u]==-1||num[v]>num[son[u]])
son[u]=v;
}
}
void getpos(int u,int root){
top[u]=root;
p[u]=pos++;
if(son[u]==-1)
return ;
getpos(son[u],root);
for(int i=head[u]; i!=-1; i=next1[i]){
int v=to[i];
if(v==son[u]||v==fath[u])
continue;
getpos(v,v);
}
}
struct TREE{
LL milt,sum;
}root[N*3];
LL cost[N]; void pushUp(int k){
root[k].sum=root[k<<1].sum+root[k<<1|1].sum;
}
void pushDow(int k){
if(root[k].milt!=1)
{
root[k<<1].sum*=root[k].milt;
root[k<<1].milt*=root[k].milt; root[k<<1|1].sum*=root[k].milt;
root[k<<1|1].milt*=root[k].milt;
root[k].milt=1;
}
}
void build(int l, int r, int k){
root[k].milt=1;
if(l==r){
root[k].sum=cost[l]; return ;
}
int mid=(l+r)>>1;
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
pushUp(k);
}
void update_C(int l, int r, int k, const int& id, LL c){
if(l==r){
root[k].sum=c; return ;
}
int mid=(l+r)>>1;
pushDow(k);
if(id<=mid)
update_C(l,mid,k<<1,id,c);
else
update_C(mid+1,r,k<<1|1,id,c);
pushUp(k);
}
void updata_M(int l,int r,int k,int L,int R,int M){
if(L<=l&&r<=R){
root[k].milt*=M; root[k].sum*=M;
return ;
}
pushDow(k);
int mid=(l+r)>>1;
if(L<=mid)
updata_M(l,mid,k<<1,L,R,M);
if(mid<R)
updata_M(mid+1,r,k<<1|1,L,R,M);
pushUp(k);
}
LL query(int l, int r, int k, const int& L, const int& R){
if(L<=l&&r<=R){
return root[k].sum;
}
pushDow(k);
int mid=(l+r)>>1;
LL sum=0;
if(L<=mid)
sum+=query(l,mid,k<<1,L,R);
if(mid<R)
sum+=query(mid+1,r,k<<1|1,L,R);
return sum;
}
void swp(int &u,int &v){
int tt=u; u=v; v=tt;
}
LL solve(int u,int v,int flag,LL M){
int fu=top[u], fv=top[v];
LL sum=0;
while(fu!=fv){
if(deep[fu]<deep[fv]){
swp(fu,fv); swp(u,v);
}
if(flag==0)
updata_M(1,pos,1,p[fu],p[u],M);
else
sum+=query(1,pos,1,p[fu],p[u]);
u=fath[fu]; fu=top[u];
}
if(u==v)return sum;
if(deep[u]>deep[v])
swp(u,v);
if(flag==0)
updata_M(1,pos,1,p[son[u]],p[v],M);
else
sum+=query(1,pos,1,p[son[u]],p[v]);//一不小心p[son[u]]写成了p[u]让我WA了好几次(求边权用p[son[u]],求点权用p[u])
return sum;
} struct EDG{
int u,v;
LL c;
}edg[N]; int main()
{
int n,m,a,b,T;
char op[10];
scanf("%d",&T);
while(T--){
scanf("%d",&n);
init();
for(int i=1; i<n; i++){
scanf("%d%d%lld",&edg[i].u,&edg[i].v,&edg[i].c);
addUndirEdge(edg[i].u, edg[i].v);
}
dfs1(1,1,1);
getpos(1,1);
for(int i=1; i<n; i++){
if(deep[edg[i].u]>deep[edg[i].v])
swp(edg[i].u, edg[i].v);
cost[p[edg[i].v]]=edg[i].c;
}
pos=n;
build(1,pos,1); while(1){
scanf("%s",op);
if(op[0]=='E')
break;
scanf("%d%d",&a,&b);
if(op[0]=='C')
update_C(1,pos,1,p[edg[a].v],b);
else if(op[0]=='M'){
LL M;
scanf("%lld",&M);
solve(a,b,0,M);
}
else
printf("%lld\n",solve(a,b,1,1));
}
} } /**************************************************************
Problem: 1663
User: aking2015
Language: C++
Result: Accepted
Time:2696 ms
Memory:9044 kb
****************************************************************/
CSU 1663: Tree(树链剖分)的更多相关文章
- Hdu 5274 Dylans loves tree (树链剖分模板)
Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...
- POJ3237 Tree 树链剖分 边权
POJ3237 Tree 树链剖分 边权 传送门:http://poj.org/problem?id=3237 题意: n个点的,n-1条边 修改单边边权 将a->b的边权取反 查询a-> ...
- Query on a tree——树链剖分整理
树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...
- 【BZOJ-4353】Play with tree 树链剖分
4353: Play with tree Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 31 Solved: 19[Submit][Status][ ...
- SPOJ Query on a tree 树链剖分 水题
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- poj 3237 Tree 树链剖分
题目链接:http://poj.org/problem?id=3237 You are given a tree with N nodes. The tree’s nodes are numbered ...
- Codeforces Round #200 (Div. 1) D Water Tree 树链剖分 or dfs序
Water Tree 给出一棵树,有三种操作: 1 x:把以x为子树的节点全部置为1 2 x:把x以及他的所有祖先全部置为0 3 x:询问节点x的值 分析: 昨晚看完题,马上想到直接树链剖分,在记录时 ...
- poj 3237 Tree 树链剖分+线段树
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
随机推荐
- 提高MSSQL数据库性能(1)对比count(*) 和 替代count(*)
原文:提高MSSQL数据库性能(1)对比count(*) 和 替代count(*) 文章准备的数据库: Atricles 表 数据量60690000条数据 ArticleID 主键自增列+自动建立 ...
- 如何对POST请求但是URL中也有参数/GET请求但是请求体中也有参数的情况进行安全扫描
通常情况下,GET的参数都在URL中,POST的参数都在请求体中,但是如题的情况也有,像使用方法PUT.DELETE的情况也有,这些情况该如何进行安全扫描呢?
- EasyUI Tree 动态传递参数
1.问题背景 一般出现在加载的时候,传递参数给后台,进行数据筛选,然后在加载tree渲染数据.所谓动态参数,可以是你的上一级节点node,或者是根节点node. 2.涉及方法 onBeforeLoad ...
- hive 行转列,列转行
行转列: concat_ws 列转行: explode
- pip install 报错UnicodeDecodeError: 'ascii' codec can't decode byte
2017-03-23 报错原因: pip安装Python包会加载我的用户目录,我的用户目录恰好是中文的,ascii不能编码. 解决办法: python目录 Python27\Lib\site-pack ...
- cmd.exe启动参数说明
启动命令解释程序 Cmd.exe 的新范例.如果在不含参数的情况下使用,cmd 将显示操作系统的版本和版权信息. 语法 cmd [{/c | /k}] [/s] [/q] [/d] [{/a | /u ...
- oracle 12C SYS,SYSTEM用户的密码都忘记或是丢失
密码 conn / as sysdba alter user system identified by Abcd1234; manual script first -->manual_scrip ...
- 飘逸的python - 实现一个pretty函数美丽的输出嵌套字典
演示样例: d = { "root": { "folder2": { "item2": None, "item1": N ...
- Android Socket通信编程
安卓客户端通过socket与服务器端通讯一般可以按照以下几个步骤:(1).通过IP地址和端口实例化Socket,请求连接服务器:socket = new Socket(HOST, PORT); //h ...
- react-native 扫一扫功能(二维码扫描)功能开发
1.安装插件 yarn add react-native-smart-barcode 2.关联 react-native link react-native-smart-barcode 3.修改 an ...