BZOJ3631: [JLOI2014]松鼠的新家

来源:互联网 发布:省市区编码 json 编辑:程序博客网 时间:2024/04/27 19:32

Description

松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在“树”上。松鼠想邀请小熊维尼前来参观,并且还指定一份参观指南,他希望维尼能够按照他的指南顺序,先去a1,再去a2,……,最后到an,去参观新家。
可是这样会导致维尼重复走很多房间,懒惰的维尼不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。维尼是个馋家伙,立马就答应了。
现在松鼠希望知道为了保证维尼有糖果吃,他需要在每一个房间各放至少多少个糖果。因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当维尼在参观的最后到达餐厅时就不需要再拿糖果吃了。
Input

第一行一个整数n,表示房间个数
第二行n个整数,依次描述a1-an
接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。
Output

一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让维尼有糖果吃。
Sample Input

5

1 4 5 3 2

1 2

2 4

2 3

4 5

Sample Output

1

2

1

2

1

HINT

2<= n <=300000

题目传送门

这不是裸的树链剖分吗??
我的数据结构好弱啊….

代码如下:

#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>using namespace std;struct node{    int x,y,next;}a[2100000];int len,last[2100000];void ins(int x,int y){    len++;    a[len].x=x;a[len].y=y;    a[len].next=last[x];last[x]=len;}int n;int fa[310000],dep[310000],son[310000],tot[310000];void pre_tree_node(int x){    tot[x]=1;son[x]=0;    for(int k=last[x];k;k=a[k].next)    {        int y=a[k].y;        if(y!=fa[x])        {            fa[y]=x;            dep[y]=dep[x]+1;            pre_tree_node(y);            if(tot[son[x]]<tot[y])son[x]=y;            tot[x]+=tot[y];        }    }}int z,ys[310000],top[310000];void pre_tree_edge(int x,int tp){    ys[x]=++z;top[x]=tp;    if(son[x]!=0)pre_tree_edge(son[x],tp);    for(int k=last[x];k;k=a[k].next)    {        int y=a[k].y;        if(y!=fa[x]&&y!=son[x])            pre_tree_edge(y,y);    }}struct trnode{    int l,r,lc,rc,c;    int lazy;}tr[2100000];int trlen;void bt(int l,int r){    int now=++trlen;    tr[now].l=l;tr[now].r=r;tr[now].c=0;    tr[now].lc=tr[now].rc=-1;tr[now].lazy=0;    if(l<r)    {        int mid=(l+r)/2;        tr[now].lc=trlen+1;bt(l,mid);        tr[now].rc=trlen+1;bt(mid+1,r);    }}void change(int now,int l,int r,int c){    if(tr[now].l==l&&tr[now].r==r){tr[now].lazy+=c;return ;}    int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;    if(mid+1<=l)change(rc,l,r,c);    else if(r<=mid)change(lc,l,r,c);    else    {        change(lc,l,mid,c);        change(rc,mid+1,r,c);    }}void update(int x){    int lc=tr[x].lc,rc=tr[x].rc;    tr[x].c=tr[x].c+tr[x].lazy;    if(lc!=-1)tr[lc].lazy+=tr[x].lazy;    if(rc!=-1)tr[rc].lazy+=tr[x].lazy;    tr[x].lazy=0;}int finds(int now,int l,int r){    if(tr[now].l==l&&tr[now].r==r)    {        update(now);        return tr[now].c;    }    int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;    if(tr[now].lazy!=0)update(now);    if(r<=mid)return finds(lc,l,r);    else return finds(rc,l,r);}void solve(int x,int y){    int tx=top[x],ty=top[y];    while(tx!=ty)    {        if(dep[tx]>dep[ty])swap(x,y),swap(tx,ty);        change(1,ys[ty],ys[y],1);        y=fa[ty];ty=top[y];    }    if(x==y)    {        change(1,ys[x],ys[x],1);        return ;    }    else    {        if(dep[x]>dep[y])swap(x,y);        change(1,ys[x],ys[y],1);        return ;    }}int ans[311000];int t[311000];int main(){    scanf("%d",&n);    len=0;memset(last,0,sizeof(last));    for(int i=1;i<=n;i++)scanf("%d",&t[i]);    for(int i=1;i<n;i++)    {        int x,y;        scanf("%d%d",&x,&y);        ins(x,y);ins(y,x);    }    fa[1]=0;dep[1]=1;    pre_tree_node(1);    z=0;pre_tree_edge(1,1);    trlen=0;bt(1,z);    for(int i=2;i<=n;i++)        solve(t[i],t[i-1]);    ans[t[1]]=finds(1,ys[t[1]],ys[t[1]]);    for(int i=2;i<=n;i++)ans[t[i]]=finds(1,ys[t[i]],ys[t[i]])-1;    for(int i=1;i<=n;i++)printf("%d\n",ans[i]);    return 0;}

by_lmy

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 hehe 度秘 坚果新机四摄曝光呵呵 为什么聊天止于呵呵 呵字开头的成语 一个呵字代表了什么 呵护 呵护的意思 另一种呵护 呵护作文 呵护的拼音 启善呵护膏 呵护有加 呵护嘴唇 嘴唇呵护 呵护生命 呵护图片 你应该被呵护被珍惜什么歌 启善婴儿呵护膏 呵护的近义词 呵护什么意思 呵护作文600字初中 被呵护被珍惜是什么歌 爱呵护纸尿裤怎么样 你应该被呵护 呵护作文500字 呵护是什么意思 背后痒 满身痒 下痒 呶呶不休 呶怎么读 呶呶不休的意思 根呷 艋呷 呷饭 呷呷瘦 呷嗽