其他分享
首页 > 其他分享> > CF276E Little Girl and Problem on Trees 题解

CF276E Little Girl and Problem on Trees 题解

作者:互联网

CF276E Little Girl and Problem on Trees 题解

CF276E

题意

略。

分析

首先处理出所有链,对于修改操作,可以分两种情况讨论。设当前节点为 \(u\) ,距离为 \(d\) ,位于第 \(num\) 条链,在根以下第 \(depth\) 层。

第一种情况,若 \(depth \geq d\) ,此时操作与其它链无关。可以给每条链建一个线段树,每次给区间 \([depth-d,depth+d]\) 的节点都加上 \(x\) 。

第二种情况,若 \(depth < d\) ,此时所有在根以下 \([1,d-depth]\) 层的节点都需要加上 \(x\) ,由于每次都是对整层的节点进行操作,因此再建一棵线段树,维护每一层加上的权值。除此之外,自己链上的符合要求的节点也需要加,就按照第一种情况的做法就行,需要注意刨掉在之前加过的几层里的节点。

对于查询操作,输出它所在层加的权值加上在本链中加的权值,需要注意特判一下大根。

开线段树时需要使用 vector ,不然 \(1e5 \times 1e5\) 肯定会 MLE。

代码

#include <bits/stdc++.h>
#define int long long
#define mem(a,b) memset(a,b,sizeof(b))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> Pair;
const int inf=2139062143;
const int MAXN=1e5+7;
inline void qread(){}template<class T1,class ...T2>
inline void qread(T1 &a,T2&... b)
{
    register T1 x=0;register bool f=false;char ch=getchar();
    while(ch<'0') f|=(ch=='-'),ch=getchar();
    while(ch>='0') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    x=(f?-x:x);a=x;qread(b...);
}
inline int qmax(const int &x,const int &y){return x>y?x:y;}
inline int qmin(const int &x,const int &y){return x<y?x:y;}
int n,q,cnt,dep[MAXN],mp[MAXN],sz[MAXN];
vector<int>tree[MAXN];
vector<int>b[MAXN];
void dfs(int u,int fa,int x)
{
    int tmp=x;
    if(fa==1) tmp=++cnt;
    if(fa!=-1) b[tmp].push_back(u);
    for(auto v:tree[u])
    {
        if(fa==v) continue;
        if(fa==1||fa==-1) dfs(v,u,tmp);
        else dfs(v,u,x);
    }
}
struct Seg_Tree
{
    vector<ll>Tree,tag;
    inline ll ls(ll p){return p<<1;}
    inline ll rs(ll p){return p<<1|1;}
    inline void push_up(ll p){Tree[p]=Tree[ls(p)]+Tree[rs(p)];}
    inline void f(ll p,ll l,ll r,ll k)
    {
        tag[p]+=k;
        Tree[p]+=(r-l+1)*k;
    }
    void push_down(ll p,ll l,ll r)
    {
        ll mid=(l+r)>>1;
        f(ls(p),l,mid,tag[p]);
        f(rs(p),mid+1,r,tag[p]);
        tag[p]=0;
    }
    void update(ll p,ll l,ll r,ll L,ll R,ll k)
    {
        if(L<=l&&r<=R) 
            Tree[p]+=(r-l+1)*k,tag[p]+=k;
        else
        {
            ll mid=(l+r)>>1;
            push_down(p,l,r);
            if(L<=mid) update(ls(p),l,mid,L,R,k);
            if(R>mid) update(rs(p),mid+1,r,L,R,k);
            push_up(p);
        }
    }
    ll query(ll p,ll l,ll r,ll L,ll R)
    {
        if(L<=l&&r<=R) return Tree[p];
        else
        {
            ll mid=(l+r)>>1,res=0;
            push_down(p,l,r);
            if(L<=mid) res+=query(ls(p),l,mid,L,R);
            if(R>mid) res+=query(rs(p),mid+1,r,L,R);
            return res;
        }
    }
}t1,t[MAXN];
signed main()
{
    qread(n,q);int i,j,mx=0,cnt1=0; // cnt1记录的是大根加的权值
    for(i=0;i<n-1;i++)
    {
        int u,v;qread(u,v);
        tree[u].push_back(v);
        tree[v].push_back(u);
    }
    dfs(1,-1,0); // 处理出每条链
    for(i=1;i<=cnt;i++) 
    {
        b[i].insert(b[i].begin(),0);
        for(j=1;j<b[i].size();j++) 
        {
            mp[b[i][j]]=i; // 记录节点所在链的编号
            dep[b[i][j]]=j; // 记录节点在根下的层数
        }
        mx=qmax(mx,b[i].size()-1); // 最大深度
        sz[i]=b[i].size()-1; // 链的长度
    }
    for(i=1;i<=cnt;i++)
    {
        t[i].Tree.resize(mx<<2);
        t[i].tag.resize(mx<<2);
    }
    t1.tag.resize(mx<<2);t1.Tree.resize(mx<<2);
    while(q--)
    {
        int op,u,x,d;qread(op,u);
        int depth=dep[u],num=mp[u];
        if(op) // 查询
        {
            if(u==1) printf("%d\n",cnt1);
            else printf("%d\n",t1.query(1,1,mx,depth,depth)+t[num].query(1,1,sz[num],depth,depth));
        }
        else
        {
            qread(x,d);
            if(u==1) // 特别处理为大根的情况
            {
                cnt1+=x;
                t1.update(1,1,mx,1,qmin(d,mx),x);
                continue;
            }
            if(depth-d>=0) // 不牵扯其它链
            {
                t[num].update(1,1,sz[num],depth-d,qmin(depth+d,sz[num]),x);
                if(depth==d) cnt1+=x;
            }
            else // 牵扯其它链
            {
                cnt1+=x;
                if(d-depth+1<=sz[num]) t[num].update(1,1,sz[num],qmin(d-depth+1,sz[num]),qmin(depth+d,sz[num]),x);
                t1.update(1,1,mx,1,qmin(d-depth,mx),x);
            }
        }
    }
    return 0;
}

标签:Little,int,题解,ll,Trees,fa,depth,long,节点
来源: https://www.cnblogs.com/lxy-2022/p/CF276E-Solution.html