树链剖分模板题,改了一下午简直疯了,最后拿来别人的代码对拍,发现自己的线段树写挫了,mdzz.
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N=50010;
struct edge{
int v,next;
}e[100010];
int qx,n,te,m,p,sz;
int val[N],size[N],h[N],num[N],head[N],tree[N],fa[N],tp[N];
struct seg{
int l,r,sum,tag;
}tr[200010];
void add(int u,int v)
{
e[++te].v=v;
e[te].next=head[u];
head[u]=te;
}
void clear()
{
memset(size,0,sizeof(size));memset(num,0,sizeof(num));
memset(head,0,sizeof(head));memset(tp,0,sizeof(tp));
sz=te=size[0]=0,h[1]=fa[1]=1;
}
inline int F()
{
register int aa,bb;register char ch;
while (ch=getchar(),(ch<'0'||ch>'9')&&ch!='-');ch=='-'?aa=bb=0:(aa=ch-'0',bb=1);
while (ch=getchar(),ch>='0'&&ch<='9')aa=(aa<<3)+(aa<<1)+ch-'0';return bb?aa:-aa;
}
void pushdown(int k)
{
if (tr[k].tag&&tr[k].r>tr[k].l)
{
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
tr[k<<1].sum+=tr[k].tag*(mid-l+1);
tr[k<<1].tag+=tr[k].tag;
tr[k<<1|1].sum+=tr[k].tag*(r-mid);
tr[k<<1|1].tag+=tr[k].tag;
tr[k].tag=0;
}
}
void dfs1(int x)
{
size[x]=1;
for (int i=head[x];i;i=e[i].next)
{
int v=e[i].v;
if (fa[x]==v)continue;
fa[v]=x;
h[v]=h[x]+1;
dfs1(v);
size[x]+=size[v];
}
}
void dfs2(int x,int chain)
{
tp[x]=chain;
num[x]=++sz;
int k=0;
for (int i=head[x];i;i=e[i].next)
{
int v=e[i].v;
if (h[v]>h[x]&&size[v]>size[k])k=v;
}
if (k==0)return;
dfs2(k,chain);
for (int i=head[x];i;i=e[i].next)
{
int v=e[i].v;
if (h[v]>h[x]&&v!=k)
dfs2(v,v);
}
}
void build(int k,int l,int r)
{
tr[k].l=l,tr[k].r=r;
if (l==r){tr[k].tag=0;tr[k].sum=val[tree[l]];return;}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;
tr[k].tag=0;
}
void change(int k,int ql,int qr,int y)
{
int l=tr[k].l,r=tr[k].r;
// cout<<l<<' '<<r<<' '<<ql<<' '<<qr<<endl;
if (ql<=l&&qr>=r)
{
tr[k].tag+=y;
tr[k].sum+=y*(r-l+1);
return ;
}
pushdown(k);
int mid=(l+r)>>1;
if (ql<=mid)change(k<<1,ql,qr,y);
if (qr>mid)change(k<<1|1,ql,qr,y);
tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;
}
void query(int k,int x)
{
int l=tr[k].l,r=tr[k].r;
if (l==x&&r==x)
{
qx=tr[k].sum;
return;
}
pushdown(k);
int mid=(l+r)>>1;
if (x<=mid)query(k<<1,x);
if (x>mid)query(k<<1|1,x);
}
void solve_c(int x,int y,int z)
{
while (tp[x]!=tp[y])
{
if (h[tp[x]]<h[tp[y]])swap(x,y);
change(1,num[tp[x]],num[x],z);
x=fa[tp[x]];
}
if (num[x]>num[y])swap(x,y);
change(1,num[x],num[y],z);
}
int main()
{
// freopen("std.in","r",stdin);
// freopen("std.out","w",stdout);
while (~scanf("%d",&n))
{
clear();m=F(),p=F();
for (int i=1;i<=n;++i)val[i]=F();
for (int i=1;i<=m;++i)
{
int u,v;
u=F(),v=F();
add(u,v),add(v,u);
}
dfs1(1);dfs2(1,1);
for (int i=1;i<=n;++i)tree[num[i]]=i;
build(1,1,n);
char ch[5];int x,y,z;
for (int i=1;i<=p;++i)
{
scanf("%s",ch);
if (ch[0]=='Q')
{
x=F();qx=0;
query(1,num[x]);
printf("%d\n",qx);
}
else
{
x=F(),y=F(),z=F();
if (ch[0]=='D')z=-z;
solve_c(x,y,z);
}
}
}
}