• bzoj 3653


    每个点维护一颗以深度为下标,size-1为值的线段树,保存整颗子树的信息,这样就可以查询了,但是如果为每个节点都建立这么一颗树,显然会MLE,所以考虑在DFS序上建立主席树,然后每个节点原来对应的线段树树就是现在的两个线段树相减所得到的树。

      1 /**************************************************************
      2     Problem: 3653
      3     User: idy002
      4     Language: C++
      5     Result: Accepted
      6     Time:9276 ms
      7     Memory:114596 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #define min(a,b) ((a)<(b)?(a):(b))
     12 #define N 300010
     13 #define S 6000000
     14  
     15 typedef long long dnt;
     16  
     17 struct Node {
     18     dnt v;
     19     Node *ls, *rs;
     20 }pool[S], *tail=pool, *null=tail, *root[N];
     21  
     22 int n, m;
     23 int head[N], dest[N+N], next[N+N], etot;
     24 int fat[N], dep[N], siz[N], in[N], out[N], vin[N], idc, mdep;
     25  
     26 void adde( int u, int v ) {
     27     etot++;
     28     next[etot] = head[u];
     29     dest[etot] = v;
     30     head[u] = etot;
     31 }
     32 void dfs( int u ) {
     33     idc++;
     34     in[u] = idc;
     35     vin[idc] = u;
     36     siz[u] = 1;
     37     for( int t=head[u]; t; t=next[t] ) {
     38         int v=dest[t];
     39         if( v==fat[u] ) continue;
     40         fat[v] = u;
     41         dep[v] = dep[u]+1;
     42         dfs(v);
     43         siz[u] += siz[v];
     44     }
     45     out[u] = idc;
     46     if( dep[u]>mdep ) mdep=dep[u];
     47 }
     48 inline void update( Node *nd ) {
     49     nd->v = nd->ls->v + nd->rs->v;
     50 }
     51 Node *modify( Node *snd, int lf, int rg, int pos, int delta ) {
     52     Node *nnd = ++tail;
     53     if( lf==rg ) {
     54         nnd->v = snd->v + delta;
     55         return nnd;
     56     }
     57     int mid=(lf+rg)>>1;
     58     if( pos<=mid ) {
     59         nnd->ls = modify( snd->ls, lf, mid, pos, delta );
     60         nnd->rs = snd->rs;
     61     } else {
     62         nnd->ls = snd->ls;
     63         nnd->rs = modify( snd->rs, mid+1, rg, pos, delta );
     64     }
     65     update( nnd );
     66     return nnd;
     67 }
     68 dnt query( Node *nd, int lf, int rg, int L, int R ) {
     69     if( nd==null ) return 0LL;
     70     if( L<=lf && rg<=R ) 
     71         return nd->v;
     72     int mid=(lf+rg)>>1;
     73     dnt rt = 0LL;
     74     if( L<=mid ) rt += query( nd->ls, lf, mid, L, R );
     75     if( R>mid ) rt += query( nd->rs, mid+1, rg, L, R );
     76     return rt;
     77 }
     78 void build() {
     79     null->ls = null->rs = null;
     80     null->v = 0;
     81     root[0] = null;
     82     for( int i=1; i<=idc; i++ ) {
     83         root[i] = modify( root[i-1], 1, mdep, dep[vin[i]], siz[vin[i]]-1 );
     84     }
     85 }
     86 dnt query( int u, int k ) {
     87     dnt ans1 = (dnt) min(k,dep[u]-1) * (siz[u]-1);
     88     dnt ans2 = 0LL;
     89     if( siz[u]==1 ) return ans1;
     90  
     91     ans2 += query( root[out[u]], 1, mdep, dep[u]+1, min( dep[u]+k, mdep ) );
     92     ans2 -= query( root[in[u]], 1, mdep, dep[u]+1, min( dep[u]+k, mdep ) );
     93     return ans1 + ans2;
     94 }
     95 int main() {
     96     scanf( "%d%d", &n, &m );
     97     for( int i=1,u,v; i<n; i++ ) {
     98         scanf( "%d%d", &u, &v );
     99         adde( u, v );
    100         adde( v, u );
    101     }
    102     fat[1] = 1;
    103     dep[1] = 1;
    104     dfs(1);
    105     build();
    106     for( int t=1,u,k; t<=m; t++ ) {
    107         scanf( "%d%d", &u, &k );
    108         printf( "%lld
    ", query(u,k) );
    109     }
    110 }
    View Code
  • 相关阅读:
    Python之数学(math)和随机数(random)
    《图解HTTP》读书笔记
    leetcode1008
    leetcode1007
    leetcode1006
    leetcode1005
    leetcode218
    leetcode212
    leetcode149
    leetcode140
  • 原文地址:https://www.cnblogs.com/idy002/p/4395651.html
Copyright © 2020-2023  润新知