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
  • 相关阅读:
    函数式编程语言
    Http
    小解_beginthreadex与_beginthreadex和CreateThread的区别
    Ring0句柄表遍历
    异步读写(ReadFileEx和ReadFile)之overlapped
    异步读写之利用完成历程
    windows核心编程第17章 一个文件两个缓存
    windows核心编程第17章 一个文件一个缓存
    windows核心编程第17章 一个文件 0个缓存
    进程间通信之利用CreateFilemapping()
  • 原文地址:https://www.cnblogs.com/jimzeng/p/bzoj3631.html
Copyright © 2011-2022 走看看