• bzoj 3772


    感觉做这种题收获很大。

    1、DFS序(广义上)除了用于静态子树操作,也可以用来做点到根的路上某些信息的统计(如点到根的路径上标记了多少个点),如果在加上lca,就可以支持路径的信息查询。

    2、树上的可持久化线段树,如果每个节点要维护一个线段树,并且该线段树支持加减操作,那么通过可持久化+lca,搞定一条路径上的线段树的和(当然不仅局限于线段树)。

    3、一条树上的路径覆盖另一条路径 <=> 后者的两个端点在前者的路径上。

    题解看PoPoQQQ的博客:

    http://blog.csdn.net/popoqqq/article/details/43122821

    如果不清楚就看看代码。

      1 /**************************************************************
      2     Problem: 3772
      3     User: idy002
      4     Language: C++
      5     Result: Accepted
      6     Time:5824 ms
      7     Memory:65180 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <vector>
     12 #define N 100010
     13 #define S 4000000
     14 #define P 16
     15 using namespace std;
     16  
     17 typedef long long dnt;
     18  
     19 struct Node {
     20     int s;
     21     Node *ls, *rs;
     22 }pool[S], *tail=pool, *root[N], *null=pool;
     23 struct Qry {
     24     int u, v;
     25     Qry(){}
     26     Qry( int u, int v ):u(u),v(v){}
     27 };
     28  
     29 int n, m;
     30 int head[N], dest[N+N], next[N+N], ntot;
     31 int in[N], out[N], idc;
     32 int anc[N][P+1], dep[N];
     33 vector<int> vc[N];
     34 Qry qry[N];
     35  
     36 void insert( int u, int v ) {
     37     ntot++;
     38     next[ntot] = head[u];
     39     dest[ntot] = v;
     40     head[u] = ntot;
     41 }
     42 Node *modify( Node *nd, int lf, int rg, int pos, int delta ) {
     43     Node *rt = ++tail;
     44     if( lf==rg ) {
     45         rt->s = nd->s + delta;
     46         return rt;
     47     }
     48     int mid=(lf+rg)>>1;
     49     if( pos<=mid ) {
     50         rt->ls = modify( nd->ls, lf, mid, pos, delta );
     51         rt->rs = nd->rs;
     52     } else {
     53         rt->ls = nd->ls;
     54         rt->rs = modify( nd->rs, mid+1, rg, pos, delta );
     55     }
     56     rt->s = rt->ls->s + rt->rs->s;
     57     return rt;
     58 }
     59 int query( Node *nd, int lf, int rg, int L, int R ) {
     60     if( L<=lf && rg<=R ) return nd->s;
     61     int mid=(lf+rg)>>1;
     62     int rt = 0;
     63     if( L<=mid ) rt += query( nd->ls, lf, mid, L, R );
     64     if( R>mid ) rt += query( nd->rs, mid+1, rg, L, R );
     65     return rt;
     66 }
     67 int query( Node *p1, Node *p2, Node *p3, Node *p4, int L, int R ) {
     68     /*  (p1+p2-p3-p4) as one tree  */
     69     int s1, s2, s3, s4;
     70     s1 = query(p1,1,idc,L,R);
     71     s2 = query(p2,1,idc,L,R);
     72     s3 = query(p3,1,idc,L,R);
     73     s4 = query(p4,1,idc,L,R);
     74     return s1+s2-s3-s4;
     75 }
     76 void dfs1( int u ) {
     77     in[u] = ++idc;
     78     for( int p=1; p<=P; p++ )
     79         anc[u][p] = anc[anc[u][p-1]][p-1];
     80     for( int t=head[u]; t; t=next[t] ) {
     81         int v=dest[t];
     82         if( v==anc[u][0] ) continue;
     83         anc[v][0] = u;
     84         dep[v] = dep[u]+1;
     85         dfs1(v);
     86     }
     87     out[u] = ++idc;
     88 }
     89 void dfs2( int u ) {
     90     root[u] = root[anc[u][0]];
     91     for( int t=0; t<vc[u].size(); t++ ) {
     92         int v=vc[u][t];
     93         root[u] = modify( root[u], 1, idc, in[v], +1 );
     94         root[u] = modify( root[u], 1, idc, out[v], -1 );
     95     }
     96     for( int t=head[u]; t; t=next[t] ) {
     97         int v=dest[t];
     98         if( v==anc[u][0] ) continue;
     99         dfs2(v);
    100     }
    101 }
    102 int lca( int u, int v ) {
    103     if( dep[u]<dep[v] ) swap(u,v);
    104     int t=dep[u]-dep[v];
    105     for( int p=0; t; t>>=1,p++ )
    106         if( t&1 ) u=anc[u][p];
    107     if( u==v ) return u;
    108     for( int p=P; p>=0 && anc[u][0]!=anc[v][0]; p-- )
    109         if( anc[u][p]!=anc[v][p] )
    110             u=anc[u][p], v=anc[v][p];
    111     return anc[u][0];
    112 }
    113 dnt gcd( dnt a, dnt b ) {
    114     return b ? gcd(b,a%b) : a;
    115 }
    116 int main() {
    117     scanf( "%d%d", &n, &m );
    118     for( int i=1,u,v; i<n; i++ ) {
    119         scanf( "%d%d", &u, &v );
    120         insert( u, v );
    121         insert( v, u );
    122     }
    123     for( int i=1,u,v; i<=m; i++ ) {
    124         scanf( "%d%d", &u, &v );
    125         vc[u].push_back(v);
    126         qry[i] = Qry(u,v);
    127     }
    128  
    129     anc[1][0] = 0;
    130     dep[1] = 1;
    131     dfs1(1);
    132  
    133     null->ls = null->rs = null;
    134     root[0] = null;
    135     dfs2(1);
    136  
    137     dnt cnt = 0, tot = 0, cd = 0;
    138     for( int i=1; i<=m; i++ ) {
    139         int u=qry[i].u, v=qry[i].v, ca=lca(u,v);
    140         cnt += query( root[u], root[v], root[ca], root[anc[ca][0]], in[ca], in[u] );
    141         cnt += query( root[u], root[v], root[ca], root[anc[ca][0]], in[ca], in[v] );
    142         cnt -= query( root[u], root[v], root[ca], root[anc[ca][0]], in[ca], in[ca] );
    143         cnt --;
    144     }
    145     tot = (dnt)m*(m-1)/2;
    146     cd = gcd(tot,cnt);
    147     printf( "%lld/%lld
    ", cnt/cd, tot/cd );
    148 }
    View Code
  • 相关阅读:
    [kuangbin带你飞]专题十二 基础DP1 E
    hdu 1203 I NEED A OFFER! (01背包)
    hdu 2602 Bone Collector (01背包)
    hdu 4513 吉哥系列故事——完美队形II (manacher)
    hdu 2203 亲和串 (KMP)
    hdu 1686 Oulipo (KMP)
    hdu 1251 统计难题 (字典树)
    hdu 2846 Repository (字典树)
    hdu 1711 Number Sequence (KMP)
    poj 3461 Oulipo(KMP)
  • 原文地址:https://www.cnblogs.com/idy002/p/4385256.html
Copyright © 2020-2023  润新知