P3258 [JLOI2014]松鼠的新家 (LCA,树上差分)

题目链接

题面:
在这里插入图片描述

题解:
明显是个树上差分的题目,不知道为什么当时会用树链剖分+线段树写。
a [ 1 ] – a [ 2 ] a [ 2 ] – a [ 3 ]
其中 a [ 2 ] 最终要-1。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#include<bitset>
#include<map>
#include<unordered_map>
#include<set>
namespace onlyzhao
{
    #define ui unsigned int
    #define ll long long
    #define llu unsigned ll
    #define ld long double
    #define pr make_pair
    #define pb push_back
    #define lc (cnt<<1)
    #define rc (cnt<<1|1)
    #define len(x)  (t[(x)].r-t[(x)].l+1)
    #define tmid ((l+r)>>1)
    #define forhead(x) for(int i=head[(x)];i;i=nt[i])
    #define max(x,y) ((x)>(y)?(x):(y))
    #define min(x,y) ((x)>(y)?(y):(x))
    #define one(n) for(int i=1;i<=(n);i++)
    #define rone(n) for(int i=(n);i>=1;i--)
    #define fone(i,x,n) for(int i=(x);i<=(n);i++)
    #define frone(i,n,x) for(int i=(n);i>=(x);i--)
    #define fonk(i,x,n,k) for(int i=(x);i<=(n);i+=(k))
    #define fronk(i,n,x,k) for(int i=(n);i>=(x);i-=(k))
    #define two(n,m) for(int i=1;i<=(n);i++) for(int j=1;j<=(m);j++)
    #define ftwo(i,n,j,m) for(int i=1;i<=(n);i++) for(int j=1;j<=(m);j++)
    #define cls(a) memset(a,0,sizeof(a))
    #define cls1(a) memset(a,-1,sizeof(a))
    #define clsmax(a) memset(a,0x3f,sizeof(a))
    #define clsmin(a) memset(a,0x80,sizeof(a))
    #define cln(a,num) memset(a,0,sizeof(a[0])*num)
    #define cln1(a,num) memset(a,-1,sizeof(a[0])*num)
    #define clnmax(a,num) memset(a,0x3f,sizeof(a[0])*num)
    #define clnmin(a,num) memset(a,0x80,sizeof(a[0])*num)
    #define sc(x) scanf("%d",&x)
    #define sc2(x,y) scanf("%d%d",&x,&y)
    #define sc3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define scl(x) scanf("%lld",&x)
    #define scl2(x,y) scanf("%lld%lld",&x,&y)
    #define scl3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z)
    #define scf(x) scanf("%lf",&x)
    #define scf2(x,y) scanf("%lf%lf",&x,&y)
    #define scf3(x,y,z) scanf("%lf%lf%lf",&x,&y,&z)
    #define scs(x) scanf("%s",x+1)
    #define scs0(x) scanf("%s",x)
    #define scline(x) scanf("%[^\n]%*c",x+1)
    #define scline0(x) scanf("%[^\n]%*c",x)
    #define pcc(x) putchar(x)
    #define pc(x) printf("%d\n",x)
    #define pc2(x,y) printf("%d %d\n",x,y)
    #define pc3(x,y,z) printf("%d %d %d\n",x,y,z)
    #define pck(x) printf("%d ",x)
    #define pcl(x) printf("%lld\n",x)
    #define pcl2(x,y) printf("%lld %lld\n",x,y)
    #define pcl3(x,y,z) printf("%lld %lld %d\n",x,y,z)
    #define pclk(x) printf("%lld ",x)
    #define pcf2(x) printf("%.2f\n",x)
    #define pcf6(x) printf("%.6f\n",x)
    #define pcf8(x) printf("%.8f\n",x)
    #define pcs(x) printf("%s\n",x+1)
    #define pcs0(x) printf("%s\n",x)
    #define pcline(x) printf("%d**********\n",x)

    char buffer[100001],*S,*T;
    inline char Get_Char()
    {
        if (S==T)
        {
            T=(S=buffer)+fread(buffer,1,100001,stdin);
            if (S==T) return EOF;
        }
        return *S++;
    }
    inline int read()
    {
        char c;int re=0;
        for(c=Get_Char();c<'0'||c>'9';c=Get_Char());
        while(c>='0'&&c<='9') re=re*10+(c-'0'),c=Get_Char();
        return re;
    }
};
using namespace onlyzhao;
using namespace std;

const int inf=0x3f3f3f3f;
const ll lnf=0x3f3f3f3f3f3f3f3f;
const double dnf=1e18;
const int mod=1e9+7;
const double eps=1e-8;
const double pi=acos(-1.0);
const int maxm=100100;
const int up=100000;
const int hp=13331;
const int maxn=300100;

int head[maxn],ver[maxn<<1],nt[maxn<<1],tot=1;
int f[maxn][20],d[maxn],a[maxn],ans[maxn],t,n;

void add(int x,int y)
{
    ver[++tot]=y,nt[tot]=head[x],head[x]=tot;
}

void init(void)
{
    d[1]=1;
    t=log2(n)+1;
}

void dfs(int x)
{
    forhead(x)
    {
        int y=ver[i];
        if(d[y]) continue;
        d[y]=d[x]+1;
        f[y][0]=x;
        fone(j,1,t) f[y][j]=f[f[y][j-1]][j-1];
        dfs(y);
    }
}

int lca(int x,int y)
{
    if(d[x]>d[y]) swap(x,y);
    frone(i,t,0) if(d[f[y][i]]>=d[x]) y=f[y][i];
    if(x==y) return x;
    frone(i,t,0) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    return f[x][0];
}

void dfs(int x,int fa)
{
    forhead(x)
    {
        int y=ver[i];
        if(y==fa) continue;
        dfs(y,x);
        ans[x]+=ans[y];
    }
}

int main(void)
{
    sc(n);
    one(n) sc(a[i]);
    int x,y;
    one(n-1)
    {
        sc2(x,y);
        add(x,y);
        add(y,x);
    }
    init();
    dfs(1);
    one(n-1)
    {
        ans[a[i]]++,ans[a[i+1]]++;
        int ca=lca(a[i],a[i+1]);
        ans[ca]--;
        ans[f[ca][0]]--;
    }
    dfs(1,0);
    fone(i,2,n) ans[a[i]]--;
    one(n) pc(ans[i]);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值