type node=^link;
link=record
des:longint;
next:node;
end; type seg=record
z,y,lc,rc,toadd,sum:longint;
end; var
n,tot,i,t1,t2,q,a,b,c:longint;
p:node;
son,siz,dep,fa,num,top:array[..] of longint;
tr:array[..] of seg;
nd:array[..] of node; function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end; function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end; procedure dfs1(po:longint);
var
p:node;
begin
siz[po]:=;son[po]:=;
p:=nd[po];
while p<>nil do
begin
if dep[p^.des]= then
begin
dep[p^.des]:=dep[po]+;
fa[p^.des]:=po;
dfs1(p^.des);
if siz[p^.des]>siz[son[po]] then
son[po]:=p^.des;
siz[po]:=siz[po]+siz[p^.des];
end;
p:=p^.next;
end;
end;//寻找非叶子结点中儿子siz最大,记录在son中 procedure dfs2(po,tp:longint);
var
p:node;
begin
inc(tot);
num[po]:=tot;
top[po]:=tp;
if son[po]<> then
dfs2(son[po],tp); p:=nd[po];
while p<>nil do
begin
if (p^.des<>son[po]) and (p^.des<>fa[po]) then dfs2(p^.des,p^.des);
p:=p^.next;
end;
end;//将重边练成重链,num记录树上的点哈希到线段树上的结果 procedure buildtree(l,r:longint);
var
t:longint;
begin
inc(tot);
tr[tot].sum:=;tr[tot].toadd:=;
tr[tot].z:=l;tr[tot].y:=r;
t:=tot;
if l=r then exit else
begin
tr[t].lc:=tot+;
buildtree(l,(l+r) div );
tr[t].rc:=tot+;
buildtree((l+r) div +,r);
end;
end;//建线段树 procedure add(po,l,r,k:longint);
var
mid:longint;
begin
if tr[po].toadd<> then
begin
tr[po].sum:=tr[po].sum+(tr[po].y-tr[po].z+)*tr[po].toadd;
tr[tr[po].lc].toadd:=tr[tr[po].lc].toadd+tr[po].toadd;
tr[tr[po].rc].toadd:=tr[tr[po].rc].toadd+tr[po].toadd;
tr[po].toadd:=;
end; mid:=(tr[po].z+tr[po].y) div ;
tr[po].sum:=tr[po].sum+(r-l+)*k;
if (l=tr[po].z) and (r=tr[po].y) then
begin
tr[tr[po].lc].toadd:=tr[tr[po].lc].toadd+k;
tr[tr[po].rc].toadd:=tr[tr[po].rc].toadd+k;
exit;
end else
begin
if mid>=l then add(tr[po].lc,l,min(mid,r),k);
if r>mid then add(tr[po].rc,max(mid+,l),r,k);
end;
end;//线段树加 function ans(po,l,r:longint):longint;
var
mid:longint;
begin
if tr[po].toadd<> then
begin
tr[po].sum:=tr[po].sum+(tr[po].y-tr[po].z+)*tr[po].toadd;
tr[tr[po].lc].toadd:=tr[tr[po].lc].toadd+tr[po].toadd;
tr[tr[po].rc].toadd:=tr[tr[po].rc].toadd+tr[po].toadd;
tr[po].toadd:=;
end; mid:=(tr[po].z+tr[po].y) div ;
if (l=tr[po].z) and (r=tr[po].y) then
exit(tr[po].sum) else
begin
ans:=;
if mid>=l then ans:=ans+ans(tr[po].lc,l,min(mid,r));
if r>mid then ans:=ans+ans(tr[po].rc,max(mid+,l),r);
end;
end;//线段树求和 procedure plus(b,c:longint);
begin
while top[b]<>top[c] do
begin
if dep[top[b]]<dep[top[c]] then
begin
add(,num[top[c]],num[c],);
c:=fa[top[c]];
end
else
begin
add(,num[top[b]],num[b],);
b:=fa[top[b]];
end;
end;
if num[b]<num[c] then add(,num[b],num[c],) else add(,num[c],num[b],);
end;//通过重链寻找被修改的区间 function query(b,c:longint):longint;
begin
query:=;
while top[b]<>top[c] do
begin
if dep[top[b]]<dep[top[c]] then
begin
query:=query+ans(,num[top[c]],num[c]);
c:=fa[top[c]];
end
else
begin
query:=query+ans(,num[top[b]],num[b]);
b:=fa[top[b]];
end;
end; if num[b]<num[c] then query:=query+ans(,num[b],num[c]) else query:=query+ans(,num[c],num[b]);
end;//通过重链寻找被求和的区间 begin read(n); for i:= to n- do
begin
read(t1,t2);
new(p);
p^.des:=t2;p^.next:=nd[t1];nd[t1]:=p;
new(p);
p^.des:=t1;p^.next:=nd[t2];nd[t2]:=p;
end; dep[]:=;
dfs1(); dfs2(,); tot:=;
buildtree(,n); read(q);
for i:= to q do
begin
read(a,b,c); if a= then plus(b,c); if a= then writeln(query(b,c));
end;
end.

————————————————————————————————————————————————————————————————

c++(BZOJ1036)

#include <cstdio>
#include <iostream>
#define LL long long
using namespace std; int next[],des[],nd[],bt[],son[],maxi[];
int fa[],dep[],size[],id[],top[],a[],revid[];
int cnt,n,q; struct node{
int l,r,lc,rc,maxi,sum;
}tr[]; void swp(int &x,int &y){
int t=x;x=y;y=t;
} void addedge(int x,int y){
next[++cnt]=nd[x];des[cnt]=y;nd[x]=cnt;
next[++cnt]=nd[y];des[cnt]=x;nd[y]=cnt;
} void dfs1(int po){
bt[po]=;
son[po]=-;maxi[po]=-;
size[po]=;
for (int p=nd[po];p!=-;p=next[p])
if (bt[des[p]]==){
fa[des[p]]=po;dep[des[p]]=dep[po]+;
dfs1(des[p]);
size[po]+=size[des[p]];
if (size[des[p]]>maxi[po]){
maxi[po]=size[des[p]];
son[po]=des[p];
}
}
} void dfs2(int po,int tp){
id[po]=++cnt;top[po]=tp;
if (son[po]==-) return; dfs2(son[po],tp);
for (int p=nd[po];p!=-;p=next[p])
if(des[p]!=fa[po]&&des[p]!=son[po]) dfs2(des[p],des[p]);
} void update(int po){
tr[po].sum=tr[tr[po].lc].sum+tr[tr[po].rc].sum;
tr[po].maxi=max(tr[tr[po].lc].maxi,tr[tr[po].rc].maxi);
} void build(int l,int r){
tr[++cnt].l=l;tr[cnt].r=r;
if (l==r) {tr[cnt].sum=tr[cnt].maxi=a[revid[l]];return;} int t=cnt,mid=(l+r)>>;
tr[t].lc=cnt+;
build(l,mid);
tr[t].rc=cnt+;
build(mid+,r);
update(t);
} void edi(int po,int targ){
if (tr[po].l==tr[po].r) {tr[po].sum=tr[po].maxi=a[targ];return;} int mid=(tr[po].l+tr[po].r>>);
if (targ<=mid) edi(tr[po].lc,targ);else edi(tr[po].rc,targ);
update(po);
} int getmax(int po,int l,int r){
if (l==tr[po].l&&r==tr[po].r) return(tr[po].maxi);
int mid=(tr[po].l+tr[po].r)>>; int ret=-1e9;
if (l<=mid) ret=max(ret,getmax(tr[po].lc,l,min(mid,r)));
if (r>mid) ret=max(ret,getmax(tr[po].rc,max(mid+,l),r));
return(ret);
} void QMAX(int x,int y){
int ans=-1e9;
while (top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) swp(x,y);
ans=max(ans,getmax(,id[top[x]],id[x]));
x=fa[top[x]];
}
if (dep[x]<dep[y]) swp(x,y);
ans=max(ans,getmax(,id[y],id[x]));
printf("%d\n",ans);
} int getsum(int po,int l,int r){
if (l==tr[po].l&&r==tr[po].r) return(tr[po].sum);
int mid=(tr[po].l+tr[po].r)>>; int ret=;
if (l<=mid) ret+=getsum(tr[po].lc,l,min(mid,r));
if (r>mid) ret+=getsum(tr[po].rc,max(mid+,l),r);
return(ret);
} void QSUM(int x,int y){
int ans=;
while (top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) swp(x,y);
ans+=getsum(,id[top[x]],id[x]);
x=fa[top[x]];
}
if (dep[x]<dep[y]) swp(x,y);
ans+=getsum(,id[y],id[x]);
printf("%d\n",ans);
} int main(){
scanf("%d",&n); for (int i=;i<=n;i++) nd[i]=-;
for (int i=;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
addedge(x,y);
} dep[]=;
dfs1(); cnt=;
dfs2(,);
for (int i=;i<=n;i++) revid[id[i]]=i; for (int i=;i<=n;i++) scanf("%d",&a[i]);
cnt=;
build(,n); scanf("%d",&q);
char st[];
for (int i=;i<=q;i++){
scanf("%s",&st);
int x,y;
scanf("%d%d",&x,&y); if (st[]=='M') QMAX(x,y);
if (st[]=='S') QSUM(x,y);
if (st[]=='H') a[id[x]]=y,edi(,id[x]);
}
}

——————————————————————————————————

树链剖分可对每条链单独建立线段树以减小常数

#include <cstdio>
#include <iostream>
#define LL long long
using namespace std; int next[],des[],nd[],cnt,size[],b[],fa[],dep[],son[];
int id[],rev[],top[],n,q,fr[],to[],root[],maxid[];
LL len[];
LL num[]; struct treenode{
int l,r,lc,rc;
LL num;
}tr[]; void addedge(int x,int y,LL num){
next[++cnt]=nd[x];des[cnt]=y;len[cnt]=num;nd[x]=cnt;
next[++cnt]=nd[y];des[cnt]=x;len[cnt]=num;nd[y]=cnt;
} void dfs1(int po){
size[po]=;b[po]=;
int maxi=-;
for (int p=nd[po];p!=-;p=next[p])
if (b[des[p]]==){
num[des[p]]=len[p];fa[des[p]]=po;
dep[des[p]]=dep[po]+;
dfs1(des[p]);
if (size[des[p]]>maxi){
maxi=size[des[p]];
son[po]=des[p];
}
size[po]+=size[des[p]];
}
} void dfs2(int po,int tp){
id[po]=++cnt;rev[cnt]=po;top[po]=tp; if (son[po]) dfs2(son[po],tp);
for (int p=nd[po];p!=-;p=next[p])
if (des[p]!=fa[po]&&des[p]!=son[po])
dfs2(des[p],des[p]);
} void update(LL &a,LL b,LL c){
if (b==-||c==-){
a=-;return;
}
if (1e18/b<c){
a=-;return;
}
a=b*c;
} void build(int l,int r){
tr[++cnt].l=l;tr[cnt].r=r;
if (l==r){
tr[cnt].num=num[rev[l]];return;
} int mid=(l+r)>>,t=cnt;
tr[t].lc=cnt+;
build(l,mid);
tr[t].rc=cnt+;
build(mid+,r);
update(tr[t].num,tr[tr[t].lc].num,tr[tr[t].rc].num);
} void edi(int po,int tar,LL num){
if (tr[po].l==tr[po].r) {tr[po].num=num;return;} int mid=(tr[po].l+tr[po].r)>>;
if (tar<=mid) edi(tr[po].lc,tar,num);else
edi(tr[po].rc,tar,num);
update(tr[po].num,tr[tr[po].lc].num,tr[tr[po].rc].num);
} LL getnum(int po,int l,int r){
LL ret=;
if (tr[po].l==l&&tr[po].r==r) return(tr[po].num); int mid=(tr[po].l+tr[po].r)>>;
if (l<=mid) update(ret,ret,getnum(tr[po].lc,l,min(mid,r)));
if (r>mid) update(ret,ret,getnum(tr[po].rc,max(mid+,l),r));
return(ret);
} LL query(int x,int y){
LL ret=;
while (top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]){
int t=x;x=y;y=t;
}
LL t=getnum(root[top[x]],id[top[x]],id[x]);
update(ret,ret,t);x=fa[top[x]];
}
if (dep[x]<dep[y]){
int t=x;x=y;y=t;
}
if (x==y) return(ret);
LL t=getnum(root[top[x]],id[son[y]],id[x]);
update(ret,ret,t);
return(ret);
} int main(){
scanf("%d%d",&n,&q);
for (int i=;i<=n;i++) nd[i]=-;
for (int i=;i<n;i++){
int t1,t2,t3;
scanf("%d%d%lld",&fr[i],&to[i],&t3);
addedge(fr[i],to[i],t3);
} dep[]=;
dfs1();
cnt=;
dfs2(,);
cnt=;
for (int i=;i<=n;i++) maxid[top[i]]=max(maxid[top[i]],id[i]);
for (int i=;i<=n;i++) if (i==top[i]){
root[i]=cnt+;build(id[i],maxid[i]);
} for (int i=;i<=q;i++){
int typ;
scanf("%d",&typ); if (typ==){
int x,y;LL v;
scanf("%d%d%lld",&x,&y,&v);
LL t=query(x,y);
if (t==-) printf("0\n");else printf("%lld\n",v/t);
} if (typ==){
int li;LL v;
scanf("%d%lld",&li,&v);
if (fa[fr[li]]==to[li]){
int t=fr[li];to[li]=fr[li];fr[li]=t;
}
edi(root[top[to[li]]],id[to[li]],v);
}
}
}

树链剖分(+线段树)(codevs4633)的更多相关文章

  1. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  2. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  3. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  4. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  5. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  6. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  7. 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 ...

  8. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

  9. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  10. bzoj2243[SDOI2011]染色 树链剖分+线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 9012  Solved: 3375[Submit][Status ...

随机推荐

  1. 学习myBatis - 如何配置myBatis

    这篇文章主要学习如何配置myBatis. 要学习新东西要讲究方法,要从三个层面去理解它:它是什么(what),为什么要学它(why),怎么用它(how).有了学习方法学习的效率才高. 1.myBati ...

  2. linux基础-第九单元 利用vi编辑器创建和编辑正文文件

    vi编辑器简介 什么是vi vi编辑器的操作模式 vi编辑器的3种基本模式 在vi编辑器中光标的移动 移动光标位置的键与光标移动间的关系 进入插入模式 从命令行模式进入插入模式的命令 在命令行模式下删 ...

  3. python字符串/元组/列表/字典互转

    #-*-coding:utf-8-*- #1.字典 dict = {'name': 'Zara', 'age': 7, 'class': 'First'} #字典转为字符串,返回:<type ' ...

  4. netbeans设置语言

    netbeans的界面语言 默认是按系统语言 设的. 想要自己指定的话,加上以下参数就可以了. 中文 --locale zh:CN 英文 --locale en:US 日文 --locale ja:J ...

  5. java汉化

    http://download.eclipse.org/technology/babel/babel_language_packs/R0.13.0/luna/luna.php _x86_64版本下载地 ...

  6. mybatis 插入数据时返回主键

    在使用MyBatis做持久层时,insert语句默认是不返回记录的主键值,而是返回插入的记录条数:显然,假如主键是你生成后插入的,自然你已经有主键了,显然不需要我们再去获得,所以我们这里处理的是当主键 ...

  7. STM32 DMA USART ADC

    转载自:http://www.cnblogs.com/UQYT/articles/2949794.html 这是一个综合的例子,演示了ADC模块.DMA模块和USART模块的基本使用. 我们在这里设置 ...

  8. 禁止Visual Studio启动时自动连接TFS服务器

    在默认设置情况下,Visual Studio启动时,会自动连接上次打开过的TFS服务器.这种设计能够提高开发人员的工作效率,避免每次手动连接TFS服务器. 但是在某些情景中,也会给人造成不必要的麻烦, ...

  9. 怎么修改windows命令行字体大小

    打开命令行窗口: 在标题栏处右键单击-->属性,然后更改即可

  10. [No00004D]深度思考好文:软件工程师的困境

    昨天是我一同学结婚的好日子,同学们大家聊各自的工作,有个同学突然问了我一句:我们同学中好像做软件的不多?如果再细分,好像做网络相关的更少? 回想起当时为何读计算机信息管理的专业,是因为那时听说读电脑未 ...