zoukankan      html  css  js  c++  java
  • BZOJ3631 [JLOI2014] 松鼠的新家

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3631

    Description

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

    Input

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

    Output

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

    以前第一次看到认为是倍增,现在一眼扫过去裸链剖……我还是Too young, too simple, sometimes naive. 

    这道题要求对每一个节点都输出答案,实测对整棵树自上而下递归一次记录每个节点的答案,比用普通线段树通用的询问方法能快300ms左右。

    对于某个节点,如果它不是起点则要将答案减1(因为有重复计算)。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #define rep(i,l,r) for(int i=l; i<=r; i++)
      6 #define clr(x,y) memset(x,y,sizeof(x))
      7 #define travel(x) for(Edge *p=last[x]; p; p=p->pre)
      8 using namespace std;
      9 const int maxn = 300010;
     10 struct Edge{
     11     Edge *pre;
     12     int to;
     13 }edge[maxn<<1];
     14 Edge *last[maxn],*pt;
     15 struct node{
     16     int l,r,v,t;
     17 }t[maxn<<2];
     18 int n,x,y,segnum=0,a[maxn],depth[maxn],fa[maxn],size[maxn],pos[maxn],belong[maxn],ans[maxn];
     19 bool vis[maxn];
     20 inline int read(){
     21     int ans = 0, f = 1;
     22     char c = getchar();
     23     while (!isdigit(c)){
     24         if (c == '-') f = -1;
     25         c = getchar();
     26     }
     27     while (isdigit(c)){
     28         ans = ans * 10 + c - '0';
     29         c = getchar();
     30     }
     31     return ans * f;
     32 }
     33 inline void addedge(int x,int y){
     34     pt->pre = last[x]; pt->to = y; last[x] = pt++;
     35 }
     36 void dfs1(int x){
     37     vis[x] = 1; size[x] = 1;
     38     travel(x){
     39         if (vis[p->to]) continue;
     40         depth[p->to] = depth[x] + 1;
     41         fa[p->to] = x;
     42         dfs1(p->to);
     43         size[x] += size[p->to];
     44     }
     45 }
     46 void dfs2(int x,int chain){
     47     int k = 0; pos[x] = ++segnum; belong[x] = chain;
     48     travel(x){
     49         if (depth[p->to] == depth[x] + 1 && size[p->to] > size[k])
     50         k = p->to;
     51     }
     52     if (!k) return;
     53     dfs2(k,chain);
     54     travel(x){
     55         if (p->to != k && depth[p->to] > depth[x])
     56         dfs2(p->to,p->to);
     57     }
     58 }
     59 inline void pushdown(int w){
     60     if ((!t[w].t) || t[w].l == t[w].r) return;
     61     t[w<<1].t += t[w].t; t[w<<1|1].t += t[w].t;
     62     t[w<<1].v += (t[w<<1].r - t[w<<1].l + 1) * t[w].t;
     63     t[w<<1|1].v += (t[w<<1|1].r - t[w<<1|1].l + 1) * t[w].t;
     64     t[w].t = 0;
     65 }
     66 inline void maintain(int w){
     67     t[w].v = t[w<<1].v + t[w<<1|1].v;
     68 }
     69 void build(int u,int v,int w){
     70     t[w].l = u; t[w].r = v; t[w].v = t[w].t = 0;
     71     if (u == v) return;
     72     int mid = (u + v) >> 1;
     73     build(u,mid,w<<1); build(mid+1,v,w<<1|1);
     74 }
     75 void change(int u,int v,int w){
     76     pushdown(w);
     77     if (u == t[w].l && v == t[w].r){
     78         t[w].v += v - u + 1;
     79         t[w].t += 1;
     80         return;
     81     }
     82     int mid = (t[w].l + t[w].r) >> 1;
     83     if (v <= mid) change(u,v,w<<1);
     84     else if (u > mid) change(u,v,w<<1|1);
     85     else{
     86         change(u,mid,w<<1);
     87         change(mid+1,v,w<<1|1);
     88     }
     89     maintain(w);
     90 }
     91 void getans(int u,int v,int w){
     92     pushdown(w);
     93     if (u == v){
     94         ans[u] = t[w].v;
     95         return;
     96     }
     97     int mid = (u + v) >> 1;
     98     getans(u,mid,w<<1); getans(mid+1,v,w<<1|1);
     99 }
    100 void modify(int x,int y){
    101     while (belong[x] != belong[y]){
    102         if (depth[belong[x]] < depth[belong[y]]) swap(x,y);
    103         change(pos[belong[x]],pos[x],1);
    104         x = fa[belong[x]];
    105     }
    106     if (depth[x] < depth[y]) swap(x,y);
    107     change(pos[y],pos[x],1);
    108 }
    109 int main(){
    110     n = read(); rep(i,1,n) a[i] = read();
    111     clr(last,0); pt = edge;
    112     rep(i,1,n-1){
    113         x = read(); y = read(); addedge(x,y); addedge(y,x);
    114     }
    115     clr(vis,0); depth[1] = 1; dfs1(1); dfs2(1,1);
    116     build(1,n,1);
    117     rep(i,2,n) modify(a[i],a[i-1]);
    118     getans(1,n,1);
    119     rep(i,1,n){
    120         printf("%d
    ",i == a[1] ? ans[pos[i]] : ans[pos[i]] - 1);
    121     }
    122     return 0;
    123 }
    View Code
  • 相关阅读:
    docker 部署aps.net MVC到windows容器
    docker 搭建私有仓库 harbor
    解决关于:Oracle数据库 插入数据中文乱码 显示问号???
    ionic cordova build android error: commamd failed with exit code eacces
    cordova build android Command failed with exit code EACCES
    Xcode 10 iOS12 "A valid provisioning profile for this executable was not found
    使用remix发布部署 发币 智能合约
    区块链: 编译发布智能合约
    mac 下常用命令备忘录
    JQuery fullCalendar 时间差 排序获取距当前最近的时间。
  • 原文地址:https://www.cnblogs.com/jimzeng/p/bzoj3631.html
Copyright © 2011-2022 走看看