zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    CQUOJ 10819 MUH and House of Cards
    CQUOJ 9920 Ladder
    CQUOJ 9906 Little Girl and Maximum XOR
    CQUOJ 10672 Kolya and Tandem Repeat
    CQUOJ 9711 Primes on Interval
    指针试水
    Another test
    Test
    二分图匹配的重要概念以及匈牙利算法
    二分图最大匹配
  • 原文地址:https://www.cnblogs.com/idy002/p/4385256.html
Copyright © 2011-2022 走看看