。。没想到正解,大概知道是线段树,但是不知道怎么处理,出来才知道是用dfs序,也有dalao用树剖怒艹。。然而我明明打的50分结果只有30分,A了之后看了一下别人50分的做法。。感觉我就算是暴力都打的很复杂。。有很多可以简化的东西。。要学习一下。
简洁的50分做法(来自hhh)
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define ll long long
using namespace std;
const char* fin="truetears.in";
const char* fout="truetears.out";
const int inf=0x7fffffff;
const int maxn=50007,maxm=maxn*2;
int n,m,i,j,k;
int fi[maxn],ne[maxm],la[maxm],tot;
ll a[maxn],ans;
int fa[maxn];
char ch;
void add_line(int a,int b){
tot++;
ne[tot]=fi[a];
la[tot]=b;
fi[a]=tot;
}
void add(int v,int from,int ad){
int i,j,k;
a[v]+=ad;
for (k=fi[v];k;k=ne[k])
if (la[k]!=from){
add(la[k],v,ad+1);
}
}
void getans(int v,int from){
int i,j,k;
ans+=a[v];
for (k=fi[v];k;k=ne[k])
if (la[k]!=from) getans(la[k],v);
}
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
scanf("%d%d",&n,&m);
for (i=2;i<=n;i++){
scanf("%d",&j);
fa[i]=j;
add_line(j,i);
add_line(i,j);
}
scanf("\n");
for (i=1;i<=m;i++){
scanf("%c%d",&ch,&j);
if (ch=='A'){
scanf("%d\n",&k);
add(j,fa[j],k);
}else{
scanf("\n");
ans=0;
getans(j,fa[j]);
cout<<ans<<endl;
}
}
return 0;
}
当然还有我的满分做法:
var
i,j,k,p,n,m,tot,id,x,y:longint;
dfn,size,dep,fa,tmp:array[0..50010]of longint;
head,go,next:array[0..200000]of longint;
sum:Array[0..200000]of int64;
ds,siz:array[0..200000]of longint;
tag:array[0..200000,0..2]of longint;
ch:char;
procedure add(x,y:longint);
begin
inc(tot);
go[tot]:=y;
next[tot]:=head[x];
head[x]:=tot;
end;
procedure dfs(x:longint);
var
i,v:longint;
begin
inc(id);
dfn[x]:=id;
tmp[id]:=dep[x];
size[x]:=1;
i:=head[x];
while i<>0 do
begin
v:=go[i];
dep[v]:=dep[x]+1;
dfs(v);
size[x]:=size[x]+size[v];
i:=next[i];
end;
end;
procedure build(x,l,r:longint);
var
mid:longint;
begin
if (l=r) then
begin
siz[x]:=1;
ds[x]:=tmp[l];
exit;
end;
mid:=(l+r)div 2;
build(x*2,l,mid);
build(x*2+1,mid+1,r);
siz[x]:=siz[x*2]+siz[x*2+1];
ds[x]:=ds[x*2]+ds[x*2+1];
end;
procedure addd(x,x1,x2:longint);
begin
sum[x]:=sum[x]+x1*siz[x]+x2*ds[x];
tag[x,0]:=tag[x,0]+x1;
tag[x,1]:=tag[x,1]+x2;
end;
procedure update(x:longint);
begin
sum[x]:=sum[x*2]+sum[x*2+1];
end;
procedure clear(x,l,r:longint);
var
mid:longint;
begin
if (l<>r)and((tag[x,0]<>0)or(tag[x,1]<>0))then
begin
addd(x*2,tag[x,0],tag[x,1]);
addd(x*2+1,tag[x,0],tag[x,1]);
tag[x,0]:=0;
tag[x,1]:=0;
end;
end;
procedure modify(x,l1,r1,l,r,z:longint);
var
mid:longint;
begin
clear(x,l,r);
if (l1=l)and(r1=r) then
begin
addd(x,z,1);
clear(x,l,r);
exit;
end;
mid:=(l+r)div 2;
if r1<=mid then modify(x*2,l1,r1,l,mid,z)
else if mid+1<=l1 then modify(x*2+1,l1,r1,mid+1,r,z)
else
begin
modify(x*2,l1,mid,l,mid,z);
modify(x*2+1,mid+1,r1,mid+1,r,z);
end;
update(x);
end;
function query(x,l1,r1,l,r:longint):int64;
var
mid:longint;
begin
clear(x,l,r);
if (r1=r)and(l1=l) then exit(sum[x]);
mid:=(l+r)div 2;
if r1<=mid then exit(query(x*2,l1,r1,l,mid))
else if mid+1<=l1 then exit(query(x*2+1,l1,r1,mid+1,r))
else begin
exit(query(x*2,l1,mid,l,mid)+query(x*2+1,mid+1,r1,mid+1,r));
end;
end;
begin
assign(input,'truetears.in');
assign(output,'truetears.out');
reset(input);
rewrite(output);
readln(n,m);
for i:=2 to n do
begin
read(fa[i]);
add(fa[i],i);
end;
readln;
dep[1]:=1;
fa[1]:=0;
dfs(1);
build(1,1,n);
for i:=1 to m do
begin
read(ch);
if ch='Q' then
begin
readln(x);
writeln(query(1,dfn[x],dfn[x]+size[x]-1,1,id));
end
else begin
readln(x,y);
modify(1,dfn[x],dfn[x]+size[x]-1,1,id,y-dep[x]);
end;
end;
end.