[BZOJ1782][Usaco2010 Feb]slowdown 慢慢游(dfs序+线段树)

来源:互联网 发布:少儿编程 比尔盖茨 编辑:程序博客网 时间:2024/05/20 11:31

题目描述

传送门

题解

单点修改+树链查询转化成子树修改+单点查询
写链剖也嗞磁

代码

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<cmath>using namespace std;#define N 100005int n,dfs_clock;int tot,point[N],nxt[N*2],v[N*2];int in[N],out[N],sum[N*4],delta[N*4];void add(int x,int y){    ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}void dfs(int x,int fa){    in[x]=++dfs_clock;    for (int i=point[x];i;i=nxt[i])        if (v[i]!=fa)            dfs(v[i],x);    out[x]=dfs_clock;}void update(int now){    sum[now]=sum[now<<1]+sum[now<<1|1];}void pushdown(int now,int l,int r,int mid){    if (delta[now])    {        sum[now<<1]+=delta[now]*(mid-l+1);delta[now<<1]+=delta[now];        sum[now<<1|1]+=delta[now]*(r-mid);delta[now<<1|1]+=delta[now];        delta[now]=0;    }}void change(int now,int l,int r,int lr,int rr){    int mid=(l+r)>>1;    if (lr<=l&&r<=rr)    {        sum[now]+=r-l+1;        ++delta[now];        return;    }    pushdown(now,l,r,mid);    if (lr<=mid) change(now<<1,l,mid,lr,rr);    if (mid+1<=rr) change(now<<1|1,mid+1,r,lr,rr);}int query(int now,int l,int r,int x){    int mid=(l+r)>>1;    if (l==r) return sum[now];    pushdown(now,l,r,mid);    if (x<=mid) return query(now<<1,l,mid,x);    else return query(now<<1|1,mid+1,r,x);}int main(){    scanf("%d",&n);    for (int i=1;i<n;++i)    {        int x,y;scanf("%d%d",&x,&y);        add(x,y),add(y,x);    }    dfs(1,0);    for (int i=1;i<=n;++i)    {        int x;scanf("%d",&x);        printf("%d\n",query(1,1,n,in[x]));        change(1,1,n,in[x],out[x]);    }}
0 0