洛谷P3258 [JLOI2014]松鼠的新家

题目描述

松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在”树“上。

松鼠想邀请****前来参观,并且还指定一份参观指南,他希望**能够按照他的指南顺序,先去a1,再去a2,......,最后到an,去参观新家。可是这样会导致**重复走很多房间,懒惰的**不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。

**是个馋家伙,立马就答应了。现在松鼠希望知道为了保证**有糖果吃,他需要在每一个房间各放至少多少个糖果。

因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当**在参观的最后到达餐厅时就不需要再拿糖果吃了。

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1:
5
1 4 5 3 2
1 2
2 4
2 3
4 5
输出样例#1:
1
2
1
2
1

说明

2<= n <=300000

题解:

分明就是一道树链剖分模板题

可是我还是写+调花了1个*时(55555……)

好伤心啊,看来这些模板该再练练了,千万不能考试时又花这么长时间

代码:

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<string.h>
  4 using namespace std;
  5 
  6 const int MAXN = 300005;
  7 struct node{
  8     int v;
  9     node *next;
 10 }pool[2*MAXN],*h[MAXN];
 11 int cnt;
 12 int fa[MAXN],dep[MAXN],son[MAXN],sonnum[MAXN],vis[MAXN];
 13 int a[MAXN];
 14 
 15 void addedge(int u,int v){
 16     node *p=&pool[++cnt],*q=&pool[++cnt];
 17     p->v=v;p->next=h[u];h[u]=p;
 18     q->v=u;q->next=h[v];h[v]=q;     
 19 }
 20 
 21 void dfs(int u){
 22     int v;
 23     int maxson,maxnum=0;
 24     sonnum[u]=1;
 25     vis[u]=1;
 26     for(node *p=h[u];p;p=p->next)
 27         if(!vis[v=p->v]){
 28             dep[v]=dep[u]+1;
 29             fa[v]=u;
 30             dfs(v);
 31             sonnum[u]+=sonnum[v];
 32             if(sonnum[v]>maxnum) maxnum=sonnum[v],maxson=v; 
 33         }
 34     if(maxnum!=0) son[u]=maxson;
 35     else son[u]=-1;
 36 }
 37 
 38 int w[MAXN],rk[MAXN],t,top[MAXN];
 39 void dfs2(int u){
 40     int v;
 41     vis[u]=1;
 42     v=son[u];
 43     if(v!=-1){
 44         top[v]=top[u];
 45         rk[v]=++t;
 46         w[t]=v;
 47         dfs2(v);
 48     }
 49     for(node *p=h[u];p;p=p->next)
 50         if(!vis[v=p->v] && v!=son[u]){
 51             top[v]=v;
 52             rk[v]=++t;
 53             w[t]=v;
 54             dfs2(v);                
 55         }
 56 }
 57 
 58 struct tree{
 59     int v,lazy,l,r;
 60     tree *parent,*ch[2];       
 61 }d[MAXN*8],*root;
 62 int cnt1;
 63 void Build_Tree(tree *p,int l,int r){
 64     p->l=l;p->r=r;
 65     d[t].v=0;d[t].lazy=0;
 66     if(l==r) return;
 67     int mid=(l+r)/2;
 68     p->ch[0]=&d[++cnt1];p->ch[1]=&d[++cnt1];
 69     Build_Tree(p->ch[0],l,mid);
 70     Build_Tree(p->ch[1],mid+1,r);
 71 }
 72 void change(tree *p,int l,int r,int c){
 73     if(p->l==l && p->r==r){
 74         p->lazy+=c;
 75         return;           
 76     }
 77     if(p->lazy){
 78         p->ch[0]->lazy+=p->lazy;
 79         p->ch[1]->lazy+=p->lazy;
 80         p->lazy=0;            
 81     }
 82     if(l>=p->ch[1]->l) change(p->ch[1],l,r,c);
 83     else if(r<=p->ch[0]->r) change(p->ch[0],l,r,c);
 84     else{
 85         change(p->ch[0],l,p->ch[0]->r,c);
 86         change(p->ch[1],p->ch[1]->l,r,c);     
 87     }
 88 }
 89 int query(tree *p,int l,int r){
 90     if(p->l==l && p->r==r){
 91         return p->lazy;           
 92     }
 93     if(p->lazy){
 94         p->ch[0]->lazy+=p->lazy;
 95         p->ch[1]->lazy+=p->lazy;
 96         p->lazy=0;
 97     }
 98     if(l>=p->ch[1]->l) return query(p->ch[1],l,r);
 99     else if(r<=p->ch[0]->r) return query(p->ch[0],l,r);
100     else{
101         return query(p->ch[0],l,p->ch[0]->r)+query(p->ch[1],p->ch[1]->l,r);     
102     }
103 }
104 
105 void lca(int x,int y){
106     int f1=top[x],f2=top[y];
107     while(f1!=f2){
108         if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
109         change(root,rk[f1],rk[x],1);
110         x=fa[f1];f1=top[x];             
111     }
112     if(dep[x]>dep[y]) swap(x,y);
113     change(root,rk[x],rk[y],1);
114 }
115 int ans[MAXN];
116 
117 int main()
118 {
119     int i,j,n,x,y;
120     scanf("%d",&n);
121     for(i=1;i<=n;i++) scanf("%d",&a[i]);
122     for(i=1;i<n;i++){
123         scanf("%d%d",&x,&y);
124         addedge(x,y);                 
125     }
126     
127     root=&d[++cnt1];
128     dep[1]=1;
129     dfs(1);
130     memset(vis,0,sizeof(vis));
131     top[1]=1;rk[1]=1;t=1;w[1]=1;
132     dfs2(1);
133     Build_Tree(root,1,t);
134     
135     for(i=1;i<n;i++) lca(a[i],a[i+1]);
136     
137     for(i=1;i<=n;i++){
138         x=query(root,i,i);
139         if(w[i]!=a[1]) x--;
140         ans[w[i]]=x;                 
141     }
142     for(i=1;i<=n;i++) printf("%d
",ans[i]);
143 
144     return 0;
145 }
View Code
既然选择了远方,便只顾风雨兼程
原文地址:https://www.cnblogs.com/lindalee/p/7706273.html