洛谷P2590 树的统计(https://www.luogu.org/problem/P2590)

啊调了6个小时,血的教训啊。。。在树链剖分后,由于树按照DFN序重新编号,如果要直接调用线段树操作,需要操作ID[X]而不能直接操作编号X

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=30030;
int head[maxn],top[maxn],dep[maxn],fa[maxn],id[maxn],sz[maxn],son[maxn];
int n,m,cnt,num,flag ,p,q,t;
int a[maxn],b[maxn];
string k;
struct pp
{
    int u;
    int nex;
}e[maxn*2];
struct kk
{
    int l,r;
    int sum,maxl;
}s[maxn*4];

void add(int x,int y)
{
    e[++cnt].u=y;
    e[cnt].nex=head[x];
    head[x]=cnt;
}
void up(int rt)
{
    s[rt].sum=s[rt<<1].sum+s[rt<<1|1].sum;
    s[rt].maxl=max(s[rt<<1].maxl,s[rt<<1|1].maxl);
}
void build(int rt,int l,int r)
{
    s[rt].l=l;
    s[rt].r=r;
    s[rt].maxl=-maxn*4;
    s[rt].sum=0;
    if(l==r)
    {
        s[rt].sum=s[rt].maxl=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    up(rt);
}
int qsum(int rt,int l,int r)
{
    if(l<=s[rt].l&&r>=s[rt].r)
     return s[rt].sum;
    int ans=0;
    int mid=(s[rt].l+s[rt].r)>>1;
    if(l<=mid) ans+=qsum(rt<<1,l,r);
    if(r>mid) ans+=qsum(rt<<1|1,l,r);
    return ans;
}
int qmax(int rt,int l,int r)
{
    if(l<=s[rt].l&&r>=s[rt].r)
     return s[rt].maxl;
    int ans=-maxn*100;
    int mid=(s[rt].l+s[rt].r)>>1;
    if(l<=mid) ans=max(ans,qmax(rt<<1,l,r));
    if(r>mid) ans=max(ans,qmax(rt<<1|1,l,r));
    return ans;
}
void modify(int rt,int x,int v)
{
    if(s[rt].l==s[rt].r&&s[rt].r==x)
    {
        s[rt].sum=s[rt].maxl=v;
        return;
    }
    int mid=(s[rt].l+s[rt].r)>>1;
    if(x<=mid) modify(rt<<1,x,v);
    else modify(rt<<1|1,x,v);
    up(rt);
}

void dfs1(int x,int f,int deep)
{
    fa[x]=f;
    dep[x]=deep;
    sz[x]=1;
    int ms=-1;
    for(int i=head[x];i;i=e[i].nex)
    {
        int y=e[i].u;
        if(y==f) continue;
        dfs1(y,x,deep+1);
        sz[x]+=sz[y];
        if(sz[y]>ms)
        {
            ms=sz[y];
            son[x]=y;
        }
    }
}

void dfs2(int x,int tt)
{
    id[x]=++num;
    a[num]=b[x];
    top[x]=tt;
    if(!son[x]) return;
    dfs2(son[x],tt);
    for(int i=head[x];i;i=e[i].nex)
    {
        int y=e[i].u;
        if(y==fa[x]||y==son[x]) continue;
        dfs2(y,y);
    }
}

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

int ansmax(int x,int y)
{
    int ans=-maxn*100;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]]) swap (x,y);
        ans=max(ans,qmax(1,id[top[x]],id[x]));
        x=fa[top[x]];
    }
    if(dep[x]<dep[y]) swap(x,y);
    ans=max(ans,qmax(1,id[y],id[x]));
    return ans;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=(n-1);i++)
    {
        int aa,bb;
        scanf("%d%d",&aa,&bb);
        add(aa,bb);add(bb,aa);
    }
    for(int i=1;i<=n;i++)
     scanf("%d",&b[i]);
    dfs1(1,0,1);
    dfs2(1,1);
    build(1,1,n); 
    scanf("%d",&t);
    while(t--)
    {
        cin>>k;
        scanf("%d%d",&p,&q);
        if(k=="CHANGE")
        modify(1,id[p],q);
        else if(k=="QMAX")
        printf("%d\n",ansmax(p,q));
        else printf("%d\n",anssum(p,q));
    }
    return 0;
}
P2590

相关文章:

  • 2021-08-05
  • 2021-06-09
  • 2021-04-20
  • 2021-09-17
  • 2021-12-04
  • 2022-12-23
  • 2021-06-09
  • 2021-09-09
猜你喜欢
  • 2021-09-04
  • 2022-12-23
  • 2021-06-26
  • 2021-06-16
  • 2021-07-19
  • 2021-04-05
  • 2022-01-07
相关资源
相似解决方案