树链剖分
才完全看懂树链剖分 我好弱啊
同学们都已经烂熟于心了 然而我却。。。
心得
先推荐大家去看 点击打开链接http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html
这个博客讲的特别的好
树链剖分 就是 两遍dfs 把这棵树的各种路都铺好 top fa son(重儿子 好势利。。) 等等的
在第二遍dfs 中 还有一个是 w数组 (signaficant) 这个数组 用来记录x作为儿子连得是第几条边 (注意是作为儿子 !因为 作为父亲可能连了好几条边)
读入优化 写的学习了
最最重要的是 也是为什么这个写法比比的写法要短的原因 : 线段树
他缩减了线段树因为在这个题目里面 根本就用不到 正常的build .l .r .val 都用不到 所以在第二遍dfs 的时候 都可以初始化好
上自己的代码
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <string.h>
using namespace std;
const int maxn = 10010;
int tr[maxn];
int zzz, n, z, root, a, b, c;
int d[maxn][3];
int head[maxn], dep[maxn], w[maxn], fa[maxn], top[maxn], son[maxn], siz[maxn];
char ch[10];
struct edge{
int to,next;
}e[maxn*2];
int cnt;
void insert (int u, int v)
{
e[++cnt].to=v;
e[cnt].next = head[u];
head[u]=cnt;
}
void dfs1(int x)
{
siz[x]=1,son[x]=0;
for(int i=head[x];i;i=e[i].next)
{
if(e[i].to!=fa[x])
{
fa[e[i].to]=x;
dep[e[i].to]=dep[x]+1;
dfs1(e[i].to);
siz[x]+=siz[e[i].to];
if(siz[e[i].to]>siz[son[x]])
son[x]=e[i].to;
}
}
}
void build_tree(int x,int tp)
{
w[x]=++z;
top[x]=tp;
if(son[x])
build_tree(son[x],top[x]);
for(int i=head[x];i;i=e[i].next)
{
if(e[i].to!=son[x]&&e[i].to!=fa[x])
{
build_tree(e[i].to,e[i].to);
}
}
}
void updata(int ro,int lt,int rt,int k,int val)
{
if(k>rt||k<lt)
return ;
if(lt==rt)
tr[ro]=val;
else
{
int mid=(lt+rt)>>1;
updata(ro<<1,lt,mid,k,val);
updata(ro<<1|1,mid+1,rt,k,val);
tr[ro]=max(tr[ro<<1],tr[ro<<1|1]);
}
}
int q(int ro,int lt,int rt,int l,int r)
{
if(l>rt||r<lt)
return 0;
if(r<=rt&&l>=lt)
return tr[ro];
int mid=(lt+rt)>>1;
return max(q(ro<<1,lt,mid,l,r),q(ro<<1|1,mid+1,rt,l,r));
}
inline int find(int a,int b)
{
int f1=top[a],f2=top[b],temp=0;
while(f1!=f2)
{
if(dep[f1]<dep[f2])
swap(f1,f2),swap(a,b);
temp=max(temp,q(1,1,z,w[f1],w[a]));
a=fa[f1];
f1=top[a];
}
if(a==b)
return temp;
if(dep[a]>dep[b])
swap(a,b);
return max(temp,q(1,1,z,w[son[a]],w[b]));
}
void init()
{
scanf("%d",&n);
root=(n+1)>>1;
fa[root]=z=dep[root]=0;
memset(head,0,sizeof(head));
memset(tr,0,sizeof(tr));
memset(siz,0,sizeof(siz));
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
d[i][0]=a;
d[i][1]=b;
d[i][2]=c;
insert(a,b);
insert(b,a);
}
dfs1(root);
build_tree (root,root);
for(int i=1;i<n;i++)
{
if(dep[d[i][0]]>dep[d[i][1]])
swap(d[i][0],d[i][1]);
updata(1,1,z,w[d[i][1]],d[i][2]);
}
}
inline void rd()
{
ch[0]=' ';
while(ch[0]<'C'||ch[0]>'Q')
scanf("%s",&ch);
}
void work()
{
for(rd();ch[0]!='D';rd())
{
scanf("%d%d",&a,&b);
if(ch[0]=='Q')
{
printf("%d",find(a,b));
}
else
{
updata(1,1,z,w[d[a][1]],b);
}
}
}
int main()
{
for(scanf("%d",&zzz);zzz>0;zzz--)
{
init();
work();
}
return 0;
}
写的很烂 毕竟我是弱弱
By LT