zoukankan      html  css  js  c++  java
  • 树链剖分 [JLOI2014]松鼠的新家

     [JLOI2014]松鼠的新家

    时间限制: 1 Sec  内存限制: 128 MB

    题目描述

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

    输入

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

    输出

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

    样例输入

    5
    1 4 5 3 2
    1 2
    2 4
    2 3
    4 5
     
    

    样例输出

    1
    2
    1
    2
    1
     

    提示

    2<= n <=300000

      树链剖分裸题,全当复习了。

      首先既然是在树上,那么两点之间的路径就是唯一的了,果断树剖,其实LCA也可以,不过时间复杂度貌似并不允许,所以放弃。

      首先,可以明确的是,我们直接从a[1]点位出发一定是最优的,不知道Q某犇为啥会纠结这个,然后就是慢慢慢慢的树剖了,然后就是一两个坑点,首先,虽然每一次树剖都是从a[i]~a[i+1],但a[i]早在求a[i-1]~a[i]时算过了,所以当我们最后输出的时候一定要记得把a[2~n]的结果-1。为什么要把a[n]的结果也减一呢?读题,a[n]是餐厅,因此不必放糖,但这并不意味着来回经过不必放糖,所以在最后一起减掉就好了。

      

      1 #include<iostream>
      2 #include<cstdlib>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<algorithm>
      6 #include<map>
      7 #include<queue>
      8 #include<string>
      9 #include<cmath>
     10 # define N 300005
     11 using namespace std;
     12 int n;
     13 int b[300005],a[300004];
     14 struct ro{
     15     int to;
     16     int next;
     17 }road[1000005];
     18 int zz;
     19 void build(int x,int y){
     20     zz++;
     21     road[zz].to=y;
     22     road[zz].next=a[x];
     23     a[x]=zz;
     24 }
     25 int deep[N],fa[N],hson[N],size[N];
     26 void dfs(int x,int dep){
     27     deep[x]=dep;
     28     size[x]=1;
     29     for(int i=a[x];i>0;i=road[i].next)
     30     {
     31         int y=road[i].to;
     32         if(fa[x]==y)continue;
     33         fa[y]=x;
     34         dfs(y,dep+1);
     35         size[x]+=size[y];
     36         if(size[hson[x]]<size[y])
     37             hson[x]=y;
     38     }
     39 }
     40 int zz2;
     41 int f2[N],dl[N],dfn[N];
     42 void dfs2(int x,int top){
     43     f2[x]=top;
     44     zz2++;
     45     dl[zz2]=x;
     46     dfn[x]=zz2;
     47     if(hson[x]) dfs2(hson[x],top);
     48     for(int i=a[x];i>0;i=road[i].next)
     49     {
     50         int y=road[i].to;
     51         if(y==fa[x]||y==hson[x]) continue;
     52         dfs2(y,y);
     53     }
     54 }
     55 struct no{
     56     int sum;
     57     int lazy;
     58     int right,left;
     59     int mid;
     60 }node[4*N];
     61 void build(int left,int right,int x){
     62     node[x].left=left;
     63     node[x].right=right;
     64     if(left==right)
     65     {
     66         return;
     67     }
     68     int mid=(left+right)/2;
     69     node[x].mid=mid;
     70     build(left,mid,2*x);
     71     build(mid+1,right,2*x+1);
     72 }
     73 void pushdown(int x){
     74     if(node[x].lazy)
     75     {
     76         node[2*x].lazy+=node[x].lazy;
     77         node[2*x+1].lazy+=node[x].lazy;
     78         node[x*2].sum+=node[x].lazy;
     79         node[2*x+1].sum+=node[x].lazy;
     80         node[x].lazy=0;
     81     }
     82 }
     83 void add(int left,int right,int x){
     84     if(node[x].left==left&&node[x].right==right)
     85     {
     86         node[x].sum++;
     87         node[x].lazy++;
     88         return;
     89     }
     90     pushdown(x);
     91     int mid=node[x].mid;
     92     if(right<=mid)
     93     {
     94         add(left,right,2*x);
     95     }
     96     else if(mid<left)
     97     {
     98         add(left,right,2*x+1);
     99     }
    100     else
    101     {
    102         add(left,mid,2*x);
    103         add(mid+1,right,2*x+1);
    104     }
    105     node[x].sum=node[x*2].sum+node[2*x+1].sum;
    106 }
    107 int get(int left,int right,int x)
    108 {
    109     if(node[x].left==node[x].right)
    110     {
    111         return node[x].sum;
    112     }
    113     pushdown(x);
    114     int mid=node[x].mid;
    115     if(left<=mid)
    116         return get(left,right,2*x);
    117     else
    118         return get(left,right,2*x+1);
    119 }
    120 void change(int x,int y){
    121      
    122     int fx=f2[x],fy=f2[y];
    123     while(fx!=fy)
    124     {
    125         if(deep[fx]<deep[fy])
    126         {
    127             swap(fx,fy);
    128             swap(x,y);
    129         }
    130         add(dfn[fx],dfn[x],1);
    131         x=fa[fx];
    132         fx=f2[x];
    133     }
    134      
    135     if(deep[y]<deep[x]) swap(y,x);
    136     if(dfn[x]<=dfn[y])
    137         add(dfn[x],dfn[y],1);
    138      
    139 }
    140 int main(){
    141     scanf("%d",&n);
    142     for(int i=1;i<=n;i++)
    143         scanf("%d",&b[i]);
    144     for(int i=1;i<n;i++)
    145     {
    146         int x,y;
    147         scanf("%d%d",&x,&y);
    148         build(x,y);
    149         build(y,x);
    150     }
    151     dfs(1,1);
    152     dfs2(1,1);
    153     build(1,n,1);
    154     for(int i=2;i<=n;i++)
    155     {
    156         change(b[i-1],b[i]);
    157     }
    158     for(int i=1;i<=n;i++)
    159     {
    160         //cout<<endl;
    161         int x=get(dfn[i],dfn[i],1);
    162         if(i!=b[1])
    163             x--;
    164         printf("%d
    ",x);
    165     }
    166     //while(1);
    167     return 0;
    168 }
    View Code
  • 相关阅读:
    for循环
    3.9 作业
    while循环
    深浅拷贝
    条件与判断
    可变与不可变
    与用户交互与运算符
    垃圾回收机制
    【AC自动机】文本生成器
    【AC自动机】最短母串
  • 原文地址:https://www.cnblogs.com/liutianrui/p/7351671.html
Copyright © 2011-2022 走看看