zoukankan      html  css  js  c++  java
  • NewTrain6 A (bzoj3631) 松鼠的新家 树剖/lca

    3631: [JLOI2014]松鼠的新家

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 2560  Solved: 1357
    [Submit][Status][Discuss]

    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

     

    题目大意:给定一棵n个节点的树和一个1~n的排列ai,对于每一个i,给从ai到ai+1的路径上除了起点以外的点都加上1,求每个点最终的值

     

    题解:

    看到题就感觉像树剖,于是就直接套板子上了。每次对于一条链来说,给左端点加上1,右端点的下一位减去1,最后做一个前缀和。注意每次是不给起点+1的,因此最后给除了a1以外的点全部-1就好了

     

    代码:

     

      1 #include<cmath>
      2 #include<math.h>
      3 #include<ctype.h>
      4 #include<algorithm>
      5 #include<bitset>
      6 #include<cassert>
      7 #include<cctype>
      8 #include<cerrno>
      9 #include<cfloat>
     10 #include<ciso646>
     11 #include<climits>
     12 #include<clocale>
     13 #include<complex>
     14 #include<csetjmp>
     15 #include<csignal>
     16 #include<cstdarg>
     17 #include<cstddef>
     18 #include<cstdio>
     19 #include<cstdlib>
     20 #include<cstring>
     21 #include<ctime>
     22 #include<cwchar>
     23 #include<cwctype>
     24 #include<deque>
     25 #include<exception>
     26 #include<fstream>
     27 #include<functional>
     28 #include<iomanip>
     29 #include<ios>
     30 #include<iosfwd>
     31 #include<iostream>
     32 #include<istream>
     33 #include<iterator>
     34 #include<limits>
     35 #include<list>
     36 #include<locale>
     37 #include<map>
     38 #include<memory>
     39 #include<new>
     40 #include<numeric>
     41 #include<ostream>
     42 #include<queue>
     43 #include<set>
     44 #include<sstream>
     45 #include<stack>
     46 #include<stdexcept>
     47 #include<streambuf>
     48 #include<string>
     49 #include<typeinfo>
     50 #include<utility>
     51 #include<valarray>
     52 #include<vector>
     53 #include<string.h>
     54 #include<stdlib.h>
     55 #include<stdio.h>
     56 using namespace std;
     57 
     58 typedef long long ll;
     59 
     60 #define pb push_back
     61 #define mp make_pair
     62 #define x first
     63 #define y second
     64 
     65 const ll inf=2147483647;
     66 
     67 //
     68 
     69 ll read()
     70 {
     71     ll x=0,f=1;
     72     char ch=getchar();
     73     while(ch<'0'||ch>'9')
     74     {
     75         if(ch=='-')f=-1;
     76         ch=getchar();
     77     }
     78     while(ch>='0'&&ch<='9')
     79     {
     80         x=x*10+ch-'0';
     81         ch=getchar();
     82     }
     83     return x*f;
     84 }
     85 
     86 void print(ll x)
     87 {
     88     if(x<0)putchar('-'),x=-x;
     89     short a[20]= {},sz=0;
     90     while(x>0)a[sz++]=x%10,x/=10;
     91     if(sz==0)putchar('0');
     92     for(ll i=sz-1; i>=0; i--)putchar('0'+a[i]);
     93 }
     94 
     95 const ll mod=1e9+7;
     96 
     97 int n;
     98 int a[333333];
     99 vector<int> adj[333333];
    100 
    101 int fa[333333];
    102 int dep[333333];
    103 int sz[333333];
    104 int son[333333];
    105 int tp[333333];
    106 int num[333333];
    107 int rnk[333333];
    108 int cnt;
    109 
    110 void dfs1(int nw,int pa,int d){
    111     fa[nw]=pa;
    112     dep[nw]=d;
    113     sz[nw]=1;
    114     for(int i=0;i<adj[nw].size();i++){
    115         int v=adj[nw][i];
    116         if(v==pa) continue;
    117         dfs1(v,nw,d+1);
    118         if(son[nw]==0 || sz[son[nw]]<sz[v]) son[nw]=v;
    119         sz[nw]+=sz[v];
    120     }
    121 }
    122 
    123 void dfs2(int nw,int t){
    124     tp[nw]=t;
    125     num[nw]=++cnt;
    126     rnk[cnt]=nw;
    127 
    128     if(son[nw]==0) return;
    129     dfs2(son[nw],t);
    130 
    131     for(int i=0;i<adj[nw].size();i++){
    132         int v=adj[nw][i];
    133         if(v==fa[nw] || v==son[nw]) continue;
    134         dfs2(v,v);
    135     }
    136 }
    137 
    138 int root;
    139 void doit(){
    140     //树链剖分
    141     root=a[1];
    142     dfs1(root,-1,0);
    143     dfs2(root,root);
    144 /*
    145     for(int i=1;i<=cnt;i++)
    146         cout<<rnk[i]<<' ';
    147     cout<<endl;*/
    148 }
    149 
    150 int ans[333333];
    151 
    152 inline void add(int a,int b){
    153     //cout<<a<<' '<<b<<endl;
    154     if(a>b) swap(a,b);
    155     ans[a]++;
    156     ans[b+1]--;
    157 }
    158 
    159 void update_path(int x,int y){
    160     int fx=tp[x],fy=tp[y];
    161     while(fx!=fy){
    162         if(dep[fx]>=dep[fy]){
    163             add(num[fx],num[x]);
    164             x=fa[fx];
    165         }
    166         else{
    167             add(num[fy],num[y]);
    168             y=fa[fy];
    169         }
    170         fx=tp[x];
    171         fy=tp[y];
    172     }
    173     add(num[x],num[y]);
    174 }
    175 
    176 int main(){
    177     //freopen("in","r",stdin);
    178     n=read();
    179     for(int i=1;i<=n;i++)
    180         a[i]=read();
    181     for(int i=1;i<n;i++){
    182         int a=read(),b=read();
    183         adj[a].pb(b);adj[b].pb(a);
    184     }
    185 
    186     doit();
    187 
    188     for(int i=1;i<n;i++){
    189         update_path(a[i],a[i+1]);
    190     }
    191 
    192     for(int i=1;i<=n;i++){
    193         ans[i]+=ans[i-1];
    194     }
    195     for(int i=2;i<=n;i++)
    196         ans[i]--;
    197 
    198     for(int i=1;i<=n;i++){
    199         printf("%d\n",ans[num[i]]);
    200     }
    201 
    202     return 0;
    203 }
    204 
    205 /*
    206 5
    207 1 4 5 3 2
    208 1 2
    209 2 4
    210 2 3
    211 4 5
    212  */
    View Code

     

     

    然后就发现自己做烦了。

    我都想到了给左端点加1右端点减1了,就没想到树上也能这样做

    每次操作,给两个端点都加上1,然后给他们的lca减去1,lca的父亲也减去1,然后在dfs一下,每个点的权值加上他的儿子们的权值。注意,输出时所有的点的权值-1,原因同上

     

    代码:

     

      1 #include<cmath>
      2 #include<math.h>
      3 #include<ctype.h>
      4 #include<algorithm>
      5 #include<bitset>
      6 #include<cassert>
      7 #include<cctype>
      8 #include<cerrno>
      9 #include<cfloat>
     10 #include<ciso646>
     11 #include<climits>
     12 #include<clocale>
     13 #include<complex>
     14 #include<csetjmp>
     15 #include<csignal>
     16 #include<cstdarg>
     17 #include<cstddef>
     18 #include<cstdio>
     19 #include<cstdlib>
     20 #include<cstring>
     21 #include<ctime>
     22 #include<cwchar>
     23 #include<cwctype>
     24 #include<deque>
     25 #include<exception>
     26 #include<fstream>
     27 #include<functional>
     28 #include<iomanip>
     29 #include<ios>
     30 #include<iosfwd>
     31 #include<iostream>
     32 #include<istream>
     33 #include<iterator>
     34 #include<limits>
     35 #include<list>
     36 #include<locale>
     37 #include<map>
     38 #include<memory>
     39 #include<new>
     40 #include<numeric>
     41 #include<ostream>
     42 #include<queue>
     43 #include<set>
     44 #include<sstream>
     45 #include<stack>
     46 #include<stdexcept>
     47 #include<streambuf>
     48 #include<string>
     49 #include<typeinfo>
     50 #include<utility>
     51 #include<valarray>
     52 #include<vector>
     53 #include<string.h>
     54 #include<stdlib.h>
     55 #include<stdio.h>
     56 using namespace std;
     57 
     58 typedef long long ll;
     59 
     60 #define pb push_back
     61 #define mp make_pair
     62 #define x first
     63 #define y second
     64 
     65 const ll inf=2147483647;
     66 
     67 //
     68 
     69 ll read()
     70 {
     71     ll x=0,f=1;
     72     char ch=getchar();
     73     while(ch<'0'||ch>'9')
     74     {
     75         if(ch=='-')f=-1;
     76         ch=getchar();
     77     }
     78     while(ch>='0'&&ch<='9')
     79     {
     80         x=x*10+ch-'0';
     81         ch=getchar();
     82     }
     83     return x*f;
     84 }
     85 
     86 void print(ll x)
     87 {
     88     if(x<0)putchar('-'),x=-x;
     89     short a[20]= {},sz=0;
     90     while(x>0)a[sz++]=x%10,x/=10;
     91     if(sz==0)putchar('0');
     92     for(ll i=sz-1; i>=0; i--)putchar('0'+a[i]);
     93 }
     94 
     95 const ll mod=1e9+7;
     96 
     97 int fa[21][333333];
     98 int n;
     99 int a[333333];
    100 vector<int> adj[333333];
    101 int tag[333333];
    102 int dep[333333];
    103 
    104 void dfs(int nw,int pa){
    105 //    cout<<nw<<' '<<pa<<endl;
    106     fa[0][nw]=pa;
    107     for(int i=0;i<adj[nw].size();i++){
    108         int v=adj[nw][i];
    109         if(v==pa) continue;
    110         dep[v]=dep[nw]+1;
    111         dfs(v,nw);
    112     }
    113 }
    114 
    115 inline int lca(int x,int y){
    116     if(x==y) return x;
    117     if(dep[x]<dep[y]) swap(x,y);
    118     for(int i=19;i>=0;i--){
    119         if(dep[fa[i][x]]>dep[y]) x=fa[i][x];
    120     }
    121     if(dep[x]>dep[y]) x=fa[0][x];
    122     if(x==y) return x;
    123     for(int i=19;i>=0;i--){
    124         if(fa[i][x]!=fa[i][y])
    125             x=fa[i][x],y=fa[i][y];
    126     }
    127     return fa[0][x];
    128 }
    129 
    130 void doit(int x,int y){
    131     int z=lca(x,y);
    132     //cout<<x<<' '<<y<<' '<<z<<endl;
    133     tag[x]++;
    134     tag[y]++;
    135     tag[z]--;
    136     tag[fa[0][z]]--;
    137 }
    138 
    139 void pushup(int nw){
    140     for(int i=0;i<adj[nw].size();i++){
    141         int v=adj[nw][i];
    142         if(v==fa[0][nw]) continue;
    143         pushup(v);
    144         tag[nw]+=tag[v];
    145     }
    146 }
    147 
    148 void hahaha(){
    149     hahaha();
    150 }
    151 
    152 int main(){
    153     //freopen("in","r",stdin);
    154     //freopen("1","w",stdout);
    155     n=read();
    156     for(int i=1;i<=n;i++)
    157         a[i]=read();
    158     a[0]=a[1];
    159 
    160     for(int i=1;i<n;i++){
    161         int fr=read(),tt=read();
    162         adj[fr].pb(tt);
    163         adj[tt].pb(fr);
    164     }
    165     adj[0].pb(a[1]);
    166 
    167     dfs(0,0);
    168 
    169     for(int i=1;i<=19;i++){
    170         for(int j=1;j<=n;j++){
    171             fa[i][j]=fa[i-1][fa[i-1][j]];
    172         }
    173     }
    174 
    175     for(int i=1;i<=n;i++)
    176         doit(a[i-1],a[i]);
    177     /*
    178     for(int i=1;i<=n;i++)
    179         printf("%d\n",tag[i]);
    180     */
    181     pushup(0);
    182 
    183     for(int i=1;i<=n;i++)
    184         printf("%d\n",tag[i]-1);
    185 
    186     return 0;
    187 }
    View Code

     

     

    无拼搏,不青春
  • 相关阅读:
    简易的观察者模式
    SSM项目实战 之 权限管理系统
    SSM项目实战 之 Shiro
    SSM项目实战 之 Maven
    SSM项目实战 之 EasyUI
    Oracle复习思路
    Oracle存储过程 函数 计算使用资源
    Mybatis笔记(二)
    Mybatis笔记(一)
    Oracle表空间 与 分页
  • 原文地址:https://www.cnblogs.com/nflslzt/p/8647787.html
Copyright © 2011-2022 走看看