树链剖分裸题
/**************************************************************
Problem: 1036
User: syh0313
Language: C++
Result: Accepted
Time:2500 ms
Memory:18068 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#define lch a[n].lc
#define rch a[n].rc
using namespace std;
const int inf=1000000000;
const int maxe=100010;
const int maxd=30010;
int nn,topt,st[maxe],to[maxe],nt[maxe],v[maxd],xx,yy,root=1,cnt,q;
int fa[maxd],rem[maxd],size[maxd],dep[maxd];
int dfn[maxd],line[maxd],dfn_num,top[maxd];
struct tree
{
int l,r,lc,rc,ma,sum;
}a[20*maxd];
bool f[maxd];
char s[20];
inline void add(int x,int y)
{to[++topt]=y; nt[topt]=st[x]; st[x]=topt;}
inline void dfs1(int x,int d)
{
dep[x]=d; size[x]=1; f[x]=1;
int p=st[x]; int ma=0;
while (p)
{
if (!f[to[p]])
{
fa[to[p]]=x;
dfs1(to[p],d+1);
size[x]+=size[to[p]];
if (size[to[p]]>ma) {ma=size[to[p]]; rem[x]=to[p];}
}
p=nt[p];
}
}
inline void dfs2(int x)
{
f[x]=1; if (rem[fa[x]]==x) top[x]=top[fa[x]];else top[x]=x;
dfn[x]=++dfn_num; line[dfn_num]=x;
if (rem[x] && !f[rem[x]]) dfs2(rem[x]);
int p=st[x];
while (p)
{
if (!f[to[p]]) dfs2(to[p]);
p=nt[p];
}
}
inline void updata(int n)
{
a[n].ma=max(a[lch].ma,a[rch].ma);
a[n].sum=a[lch].sum+a[rch].sum;
}
inline void build_tree(int &n,int l,int r)
{
n=++cnt; a[n].l=l; a[n].r=r;
if (l==r) {a[n].ma=v[line[l]]; a[n].sum=v[line[l]]; return;}
int mid=(l+r)>>1;
build_tree(lch,l,mid);
build_tree(rch,mid+1,r);
updata(n);
}
inline int qurymax(int n,int L,int R,int l,int r)
{
if (L==l && R==r) return a[n].ma;
int mid=(L+R)>>1;
if (r<=mid) return qurymax(lch,L,mid,l,r);
else if (l>=mid+1) return qurymax(rch,mid+1,R,l,r);
else return max(qurymax(lch,L,mid,l,mid),qurymax(rch,mid+1,R,mid+1,r));
}
inline int qmax(int x,int y)
{
int ans=-inf,l,r;
while (top[x]!=top[y])
{
if (dep[top[x]]<dep[top[y]]) {int cc=x; x=y; y=cc;}
ans=max(ans,qurymax(root,1,dfn_num,dfn[top[x]],dfn[x]));
x=fa[top[x]];
}
l=min(dfn[x],dfn[y]),r=max(dfn[x],dfn[y]);
ans=max(ans,qurymax(root,1,dfn_num,l,r));
return ans;
}
inline int qurysum(int n,int L,int R,int l,int r)
{
if (L==l && R==r) return a[n].sum;
int mid=(L+R)>>1;
if (r<=mid) return qurysum(lch,L,mid,l,r);
else if (l>=mid+1) return qurysum(rch,mid+1,R,l,r);
else return qurysum(lch,L,mid,l,mid)+qurysum(rch,mid+1,R,mid+1,r);
}
inline int qsum(int x,int y)
{
int sum=0,l,r;
while (top[x]!=top[y])
{
if (dep[top[x]]<dep[top[y]]) {int cc=x; x=y; y=cc;}
sum+=qurysum(root,1,dfn_num,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
l=min(dfn[x],dfn[y]),r=max(dfn[x],dfn[y]);
sum+=qurysum(root,1,dfn_num,l,r);
return sum;
}
inline void change(int n,int l,int r,int lc)
{
if (l==r && r==lc) {a[n].ma=yy; a[n].sum=yy; return;}
if (l==r) return;
int mid=(l+r)>>1;
if (lc<=mid) change(lch,l,mid,lc);
else change(rch,mid+1,r,lc);
updata(n);
}
int main()
{
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
register int i;
scanf("%d",&nn);
for (i=1;i<nn;i++)
{scanf("%d%d",&xx,&yy); add(xx,yy); add(yy,xx);}
fa[root]=1; dfs1(root,1);
memset(f,0,sizeof f); dfs2(root);
for (i=1;i<=nn;i++) scanf("%d",&v[i]);
build_tree(root,1,dfn_num);
scanf("%d",&q);
while (q--)
{
scanf("%s %d %d",s,&xx,&yy);
if (s[1]=='M') printf("%d\n",qmax(xx,yy));
else if (s[1]=='S') printf("%d\n",qsum(xx,yy));
else if (s[1]=='H') change(root,1,dfn_num,dfn[xx]);
}
return 0;
}
213

被折叠的 条评论
为什么被折叠?



