您的位置:首页 > 其它

HYSBZ 1036 【树链剖分】

2015-11-21 21:53 393 查看
思路:

裸裸的树链剖分....

树链剖分就是把一棵树分成若干重链和轻链...然后保证形成的线段树上每条链是连续存储的。然后这样就能用线段树进行维护了。

但是每次一定要保证是在同一条链里边....思路就是这样....

感觉最近越来越淡定了,题目卡住了也不怎么着急了,慢慢看代码...嗯...有点像学习的感觉了....

明天青岛理工的邀请赛要好好玩玩...

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n,m;
int myw[30100];
bool vis[30100];
int siz[30100],dep[30100],top[30100],fa[30100],son[30100],w[30100],fp[30100];
int totw;
char typ[20];
long long INF=0x3f3f3f3f3f;
struct edge
{
int id;
edge *next;
};
edge edges[30100<<1];
edge *adj[30100];
struct tr
{
int s,e,maxx;
long long sum;
};
tr tree[30100<<2];
void build(int k,int s,int e)
{
tree[k].s=s;
tree[k].e=e;
if(s==e)
{
tree[k].sum=tree[k].maxx=myw[fp[s]];
return;
}
int mid=(s+e)>>1;
build(k<<1,s,mid);
build(k<<1|1,mid+1,e);
tree[k].maxx=max(tree[k<<1].maxx,tree[k<<1|1].maxx);
tree[k].sum=tree[k<<1|1].sum+tree[k<<1].sum;
}
int ednum;
inline void AddEdge(int a,int b)
{
edge *tmp;
tmp=&edges[ednum++];
tmp->id=b;
tmp->next=adj[a];
adj[a]=tmp;
}

void dfs1(int id,int mdep,int f)
{
vis[id]=1;
dep[id]=mdep;
siz[id]=1;
fa[id]=f;
son[id]=0;
int tmpsiz=-1;
for(edge *it=adj[id]; it; it=it->next)
{
if(!vis[it->id])
{
dfs1(it->id,mdep+1,id);
if(tmpsiz<siz[it->id])
{
tmpsiz=siz[it->id];
son[id]=it->id;
}
siz[id]+=siz[it->id];
}
}
}
void dfs2(int id,int ase)
{
vis[id]=1;
top[id]=ase;
w[id]=++totw;
fp[totw]=id;
if(son[id])
dfs2(son[id],ase);
for(edge *it=adj[id]; it; it=it->next)
{
if(!vis[it->id])
{
dfs2(it->id,it->id);
}
}
}
long long ans;
void querySum(int k,int s,int e)
{
if(tree[k].e==e&&tree[k].s==s)
{
ans+=tree[k].sum;
return;
}
int mid=(tree[k].s+tree[k].e)>>1;
if(e<=mid)
{
querySum(k<<1,s,e);
}
else if(s>mid)
{
querySum(k<<1|1,s,e);
}
else
{
querySum(k<<1,s,mid);
querySum(k<<1|1,mid+1,e);
}
}
void qsum(int a,int b)
{
int f1=top[a],f2=top[b];

ans=0;
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(f1,f2);
swap(a,b);
}
querySum(1,w[f1],w[a]);
a=fa[f1];
f1=top[a];
}
if(dep[a]>dep[b])
swap(a,b);
querySum(1,w[a],w[b]);
printf("%lld\n",ans);
}
void queryMax(int k,int s,int e)
{
if(tree[k].e==e&&tree[k].s==s)
{
ans=max(ans,(long long)tree[k].maxx);
return;
}
int mid=(tree[k].s+tree[k].e)>>1;
if(e<=mid)
{
queryMax(k<<1,s,e);
}
else if(s>mid)
{
queryMax(k<<1|1,s,e);
}
else
{
queryMax(k<<1,s,mid);
queryMax(k<<1|1,mid+1,e);
}
}
void qmax(int a,int b)
{
int f1=top[a],f2=top[b];
ans=INF*(-1);
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(f1,f2);
swap(a,b);
}
queryMax(1,w[f1],w[a]);
a=fa[f1];
f1=top[a];
}
if(dep[a]>dep[b])
swap(a,b);
queryMax(1,w[a],w[b]);
printf("%lld\n",ans);
}
void update(int k,int pos,int val)
{
if(tree[k].s==tree[k].e)
{
tree[k].sum=tree[k].maxx=val;
return;
}
int mid=(tree[k].s+tree[k].e)>>1;
if(pos<=mid)
update(k<<1,pos,val);
else
update(k<<1|1,pos,val);
tree[k].sum=tree[k<<1|1].sum+tree[k<<1].sum;
tree[k].maxx=max(tree[k<<1].maxx,tree[k<<1|1].maxx);
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(siz,0,sizeof(siz));
memset(vis,0,sizeof(vis));
memset(son,0,sizeof(son));
fa[1]=0;
totw=0;
ednum=0;
for(int i=1;i<=n;i++)
{
adj[i]=NULL;
}
for(int i=1; i<n; i++)
{
int a,b;
scanf("%d%d",&a,&b);
AddEdge(a,b);
AddEdge(b,a);
}
for(int i=1; i<=n; i++)
{
scanf("%d",&myw[i]);
}
dfs1(1,1,0);
memset(vis,0,sizeof(vis));
dfs2(1,1);
build(1,1,totw);
scanf("%d",&m);
for(int i=1; i<=m; i++)
{
int a,b;
scanf("%s%d%d",typ,&a,&b);
if(typ[3]=='X')
{
qmax(a,b);
}
else if(typ[3]=='M')
{
qsum(a,b);
}
else if((typ[3]=='N'))
{
update(1,w[a],b);
}
}
}
}
/*
8
1 2
1 4
2 3
3 8
5 6
7 5
2 5
3 7 6 5 8 2 1 0
1000
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: