华华和月月种树

题目链接:https://ac.nowcoder.com/acm/contest/392/H

作者:fzszkl
链接:https://ac.nowcoder.com/discuss/160376?type=101&order=time&pos=&page=1
来源:牛客网

首先离线操作,建出整棵树的最终状态。对这棵树进行DFS,i号点被搜到的时间记为DFNiDFNi。DFN有一个重要的性质,就是同一棵子树内的节点的DFN总是连续的,所以我们可以用一个线段树按照DFN的顺序来维护所有点的点权。

考虑到一个操作会影响到一个点有以下两个条件:1、被操作的是被影响的点的祖先(或它自己);2、加点的时间早于操作的时间。

所以我们执行修改和询问时直接对整棵子树执行,执行加点操作的时候直接将这个点当前的点权**清零**即可。这样可以消除所有早于它出现的操作的影响。因为只有单点询问,所以本题线段树可用差分树状数组代替。时间复杂度O(MlogM)O(Mlog⁡M)。

#include <bits/stdc++.h>
using namespace std;
#define re register
#define ll long long
#define fi first
#define se second
#define pb push_back
const int maxn=1e5+10;
void read(int &a)
{
    a=0;
    int d=1;
    char ch;
    while(ch=getchar(),ch>'9'||ch<'0')
        if(ch=='-')
            d=-1;
    a=ch-'0';
    while(ch=getchar(),ch>='0'&&ch<='9')
        a=a*10+ch-'0';
    a*=d;
}
void write(int x)
{
    if(x<0)
        putchar(45),x=-x;
    if(x>9)
        write(x/10);
    putchar(x%10+'0');
}
struct note
{
    int op,a,x,asd;
}tmp[4*maxn];
int cnt[maxn],cnt_end[maxn],t,tree[maxn],n;
vector <int> q[maxn];
void dfs(int x)
{
    cnt[x]=++t;
    for(re int i=0;i<q[x].size();i++)
        dfs(q[x][i]);
    cnt_end[x]=t;
}
int lowbit(int k)
{
    return k&-k;
}
void add(int i,int x)
{
    while(i<=t)
    {
        tree[i]+=x;
        i+=lowbit(i);
    }
}
void add1(int l,int r,int x)
{
    add(l,x);
    add(r+1,-x);
}
ll sum(int i)
{
    ll ans=0;
    while(i)
    {
        ans+=tree[i];
        i-=lowbit(i);
    }
    return ans;
}
int main()
{
    int T;
    read(T);
    for(re int i=1;i<=T;i++)
    {
        read(tmp[i].op);
        read(tmp[i].a);
        if(tmp[i].op==1)
        {
            q[tmp[i].a].pb(++n);
            tmp[i].asd=n;
        }
        else if(tmp[i].op==2)
            read(tmp[i].x);
    }
    dfs(0);
    for(re int i=1;i<=T;i++)
    {
        if(tmp[i].op==1)
        {
            int val=sum(cnt[tmp[i].asd]);
            add1(cnt[tmp[i].asd],cnt[tmp[i].asd],-val);
        }
        else if(tmp[i].op==2)
            add1(cnt[tmp[i].a],cnt_end[tmp[i].a],tmp[i].x);
        else
            printf("%lld\n",sum(cnt[tmp[i].a]));
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/acm1ruoji/p/10668064.html
今日推荐