NOIP11.15模拟 T2 三部曲

11 篇文章 0 订阅
4 篇文章 0 订阅

。。没想到正解,大概知道是线段树,但是不知道怎么处理,出来才知道是用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.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值