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
  • 相关阅读:
    nfs-client-provisioner 利用NFS动态提供Kubernetes后端存储卷
    docker-compose简易编写和模板命令
    shell脚本自动过滤尝试多次连接ip并添加到系统黑名单
    Centos 升级glibc 亲测好用
    centos安装Jenkins报错
    centos8 安装docker启动失败
    cenots7 rpm 包升级ssh
    python备份文件(简易)
    Docker 容器基本操作(基础)
    Docker 环境下如何配置你的镜像(基础)
  • 原文地址:https://www.cnblogs.com/idy002/p/4385256.html
Copyright © 2011-2022 走看看