P3038 [USACO11DEC] Grass Planting G

原题链接

题解

树上区间修改加单点查询,虽然可以树状数组,但是线段树更通用一点
然而线段树通常处理的是点权,可这里是边权,怎么办呢?我们可以把边权转换成点权,由于每个点的子边有若干个,但父边有且只有一个,这样我们就把边权变成边下方点的点权

然后区间修改和单点求和的时候把lca的点权删掉即可

code

#include<bits/stdc++.h>
using namespace std;


vector<int> G[100005];
int n,m;
int dep[100005]={0};
int sizes[100005];
int fa[100005];
int bigson[100005]={0};
int id[100005];
int tree[400005];
int lazytag[400005];
int top[100005];
int cnt=0;

void dfs1(int now,int pre)
{
    dep[now]=dep[pre]+1;
    sizes[now]=1;
    fa[now]=pre;
    int maxson=0;
    for(auto next:G[now])
    {
        if(next==pre) continue;
        dfs1(next,now);
        if(sizes[next]>maxson)
        {
            bigson[now]=next;
            maxson=sizes[next];
        }
        sizes[now]+=sizes[next];
    }
}

void dfs2(int now,int topf)
{
    top[now]=topf;
    id[now]=++cnt;
    if(!bigson[now]) return ;
    dfs2(bigson[now],topf);

    for(auto next:G[now])
    {
        if(next==fa[now]||next==bigson[now]) continue;
        dfs2(next,next);
    }
}

void pushdown(int node,int l,int r)
{
    tree[node]+=(r-l+1)*lazytag[node];
    if(r!=l)
    {
        lazytag[node*2]+=lazytag[node];
        lazytag[node*2+1]+=lazytag[node];
    }
    lazytag[node]=0;
}

void update(int node,int l,int r,int x,int y,int v)
{
    if(lazytag[node]) pushdown(node,l,r);
    if(l>y||r<x) return;

    if(l>=x&&r<=y)
    {
        lazytag[node]+=v;
        pushdown(node,l,r);
        return;
    }

    int mid=(l+r)/2;
    update(node*2,l,mid,x,y,v);
    update(node*2+1,mid+1,r,x,y,v);
    tree[node]=tree[node*2]+tree[node*2+1];
}


int query(int node,int l,int r,int x,int y)
{
    if(lazytag[node]) pushdown(node,l,r);
    if(l>y||r<x) return 0;
    if(l>=x&&r<=y)
    {
        return tree[node];
    }

    int mid=(l+r)/2;
    return query(node*2,l,mid,x,y)+query(node*2+1,mid+1,r,x,y);
}

void add(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        update(1,1,n,id[top[x]],id[x],1);
        x=fa[top[x]];
    }
    if(dep[x]<dep[y]) swap(x,y);
    update(1,1,n,id[y],id[x],1);
    update(1,1,n,id[y],id[y],-1);
}

int sum(int x,int y)
{
    int ans=0;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap(x,y);
        ans+=query(1,1,n,id[top[x]],id[x]);
        x=fa[top[x]];
    }

    if(dep[x]<dep[y]) swap(x,y);
    ans+=query(1,1,n,id[y],id[x]);
    ans-=query(1,1,n,id[y],id[y]);
    return ans;
}


int main()
{
    cin>>n>>m;
    for(int i=1;i<n;i++)
    {
        int x,y;
        cin>>x>>y;
        G[x].push_back(y);
        G[y].push_back(x);
    }

    dfs1(1,0);
    dfs2(1,1);


    while(m--)
    {
        int x,y;
        char op;
        cin>>op>>x>>y;
        if(op=='P') add(x,y);
        else cout<<sum(x,y)<<endl;
    }
    return 0;
}

posted @   纯粹的  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示