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. java word文档 转 html文件

    一.简介 一般word文件后缀有doc.docx两种.docx是office word 2007以及以后版本文档的扩展名:doc是office word 2003文档保存的扩展名.对于这两种格式的wo ...

  2. Vim指令备忘

    从网上找来的记忆图,适合于刚上手的童鞋形象记忆. 接下来的是个人在使用过程中容易忘记的命令,特此备份查看. n<space> 会向右移动这一行的n 个字元 n<Enter> 向 ...

  3. Linux命令行上传文件到百度网盘

    利用bpcs_uploader你可以自动将VPS主机上的文件上传到百度网盘中,同时也可以从百度网盘中下载文件到VPS主机上,让你的文件安全地"住"在百度云中.[font=Tahom ...

  4. Windows Azure 虚拟机的IP地址操作

    Windows Azure上的一个虚拟机对应两个IP地址,VIP和DIP. VIP,公网IPv4地址,动态分配.虚拟机停止(deallocate,在管理控制台上关机或者使用PowerShell关机)后 ...

  5. 感觉没睡好就..-shenmedoumeixie....

    hi 昨晚没睡好,虽然梦很香,但睡不好没精神做科研啊... 1.jQuery 十二.实现聊天室创建 12.1 基本功能 登陆: 无刷新实时交流: 支持表情. 12.2 大致效果 登陆——>验证, ...

  6. 记一次惨痛的线上bug

    讲述背景,刚入职新公司2个月的时候,接手一个红包系统.资历尚浅,对业务也不是很熟悉.公司开发新的平台,需要使用红包功能来进行推广,按照产品的需求,进行开发...然而,问题就出在这里,红包接口比较陈旧, ...

  7. JAVA设计模式之工厂模式

    工厂模式概念: 实例化对象,用工厂方法代替new操作 工厂模式包括工厂方法模式和抽象工厂模式 抽象工厂模式是工厂方法模式的扩展 工厂模式的意图: 定义一个接口来创建对象,但是让子类来决定哪些类需要被实 ...

  8. HTML5 WebSocket 技术介绍

    WebSocket是html5规范新引入的功能,用于解决浏览器与后台服务器双向通讯的问题,使用WebSocket技术,后台可以随时向前端推送消息,以保证前后台状态统一,在传统的无状态HTTP协议中,这 ...

  9. Visual Studio 2015 Community连接到Mysql

    版权声明:本文为博主原创文章,未经博主允许不得转载. 本文首发于CSDN:http://blog.csdn.net/cxq2046/article/details/51108256 至今暂未授权其他任 ...

  10. 最大M子段和 V2

    51nod1053 这题还是我们熟悉的M子段和,只不过N,M<=50000. 这题似乎是一个堆+链表的题目啊 开始考虑把所有正数负数锁在一起. 比如: 1 2 3 -1 –2 -3 666 缩成 ...