感觉做这种题收获很大。

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

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

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

题解看PoPoQQQ的博客:

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

如果不清楚就看看代码。

 /**************************************************************
Problem: 3772
User: idy002
Language: C++
Result: Accepted
Time:5824 ms
Memory:65180 kb
****************************************************************/ #include <cstdio>
#include <vector>
#define N 100010
#define S 4000000
#define P 16
using namespace std; typedef long long dnt; struct Node {
int s;
Node *ls, *rs;
}pool[S], *tail=pool, *root[N], *null=pool;
struct Qry {
int u, v;
Qry(){}
Qry( int u, int v ):u(u),v(v){}
}; int n, m;
int head[N], dest[N+N], next[N+N], ntot;
int in[N], out[N], idc;
int anc[N][P+], dep[N];
vector<int> vc[N];
Qry qry[N]; void insert( int u, int v ) {
ntot++;
next[ntot] = head[u];
dest[ntot] = v;
head[u] = ntot;
}
Node *modify( Node *nd, int lf, int rg, int pos, int delta ) {
Node *rt = ++tail;
if( lf==rg ) {
rt->s = nd->s + delta;
return rt;
}
int mid=(lf+rg)>>;
if( pos<=mid ) {
rt->ls = modify( nd->ls, lf, mid, pos, delta );
rt->rs = nd->rs;
} else {
rt->ls = nd->ls;
rt->rs = modify( nd->rs, mid+, rg, pos, delta );
}
rt->s = rt->ls->s + rt->rs->s;
return rt;
}
int query( Node *nd, int lf, int rg, int L, int R ) {
if( L<=lf && rg<=R ) return nd->s;
int mid=(lf+rg)>>;
int rt = ;
if( L<=mid ) rt += query( nd->ls, lf, mid, L, R );
if( R>mid ) rt += query( nd->rs, mid+, rg, L, R );
return rt;
}
int query( Node *p1, Node *p2, Node *p3, Node *p4, int L, int R ) {
/* (p1+p2-p3-p4) as one tree */
int s1, s2, s3, s4;
s1 = query(p1,,idc,L,R);
s2 = query(p2,,idc,L,R);
s3 = query(p3,,idc,L,R);
s4 = query(p4,,idc,L,R);
return s1+s2-s3-s4;
}
void dfs1( int u ) {
in[u] = ++idc;
for( int p=; p<=P; p++ )
anc[u][p] = anc[anc[u][p-]][p-];
for( int t=head[u]; t; t=next[t] ) {
int v=dest[t];
if( v==anc[u][] ) continue;
anc[v][] = u;
dep[v] = dep[u]+;
dfs1(v);
}
out[u] = ++idc;
}
void dfs2( int u ) {
root[u] = root[anc[u][]];
for( int t=; t<vc[u].size(); t++ ) {
int v=vc[u][t];
root[u] = modify( root[u], , idc, in[v], + );
root[u] = modify( root[u], , idc, out[v], - );
}
for( int t=head[u]; t; t=next[t] ) {
int v=dest[t];
if( v==anc[u][] ) continue;
dfs2(v);
}
}
int lca( int u, int v ) {
if( dep[u]<dep[v] ) swap(u,v);
int t=dep[u]-dep[v];
for( int p=; t; t>>=,p++ )
if( t& ) u=anc[u][p];
if( u==v ) return u;
for( int p=P; p>= && anc[u][]!=anc[v][]; p-- )
if( anc[u][p]!=anc[v][p] )
u=anc[u][p], v=anc[v][p];
return anc[u][];
}
dnt gcd( dnt a, dnt b ) {
return b ? gcd(b,a%b) : a;
}
int main() {
scanf( "%d%d", &n, &m );
for( int i=,u,v; i<n; i++ ) {
scanf( "%d%d", &u, &v );
insert( u, v );
insert( v, u );
}
for( int i=,u,v; i<=m; i++ ) {
scanf( "%d%d", &u, &v );
vc[u].push_back(v);
qry[i] = Qry(u,v);
} anc[][] = ;
dep[] = ;
dfs1(); null->ls = null->rs = null;
root[] = null;
dfs2(); dnt cnt = , tot = , cd = ;
for( int i=; i<=m; i++ ) {
int u=qry[i].u, v=qry[i].v, ca=lca(u,v);
cnt += query( root[u], root[v], root[ca], root[anc[ca][]], in[ca], in[u] );
cnt += query( root[u], root[v], root[ca], root[anc[ca][]], in[ca], in[v] );
cnt -= query( root[u], root[v], root[ca], root[anc[ca][]], in[ca], in[ca] );
cnt --;
}
tot = (dnt)m*(m-)/;
cd = gcd(tot,cnt);
printf( "%lld/%lld\n", cnt/cd, tot/cd );
}

bzoj 3772的更多相关文章

  1. bzoj 3772 :精神污染 线段树+打标记 or 主席树

    3772: 精神污染 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 315  Solved: 87[Submit][Status][Discuss] D ...

  2. BZOJ 3772: 精神污染 (dfs序+树状数组)

    跟 BZOJ 4009: [HNOI2015]接水果一样- CODE #include <set> #include <queue> #include <cctype&g ...

  3. 【BZOJ 3772】精神污染 主席树+欧拉序

    这道题的内存…………………真·精神污染……….. 这道题的思路很明了,我们就是要找每一个路径包含了多少其他路径那么就是找,有多少路径的左右端点都在这条路径上,对于每一条路径,我们随便选定一个端点作为第 ...

  4. bzoj 3772 精神污染 主席树+dfs序

    精神污染 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 637  Solved: 177[Submit][Status][Discuss] Descri ...

  5. BZOJ 3772: 精神污染(dfs序+主席树)

    传送门 解题思路 比较神仙的一道题.首先计算答案时可以每条路径所包含的路径数,对于\(x,y\)这条路径,可以在\(x\)这处开个\(vector\)存\(y\),然后计算时只需要算这个路径上每个点的 ...

  6. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  7. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  8. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  9. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

随机推荐

  1. NYOJ 925 国王的烦恼 (并查集)

    题目链接 描述     C国由n个小岛组成,为了方便小岛之间联络,C国在小岛间建立了m座大桥,每座大桥连接两座小岛.两个小岛间可能存在多座桥连接.然而,由于海水冲刷,有一些大桥面临着不能使用的危险.如 ...

  2. PHP中的 get_magic_quotes_runtime

    get_magic_quotes_runtime() 获得外部文件及数据库资料时是否进行转义 set_magic_quotes_runtime(1); 临时设置获得外部文件及数据库资料时是否进行转义 ...

  3. webstrom 里面使用github

    1.输入github的账号和密码,点击登录 2.复制github的项目地址,现在clone就行了

  4. samba中的pdbedit用法

    pdbedit用于在samba服务器中创建用户: 它的用法包括 pdbedit -a username:新建Samba账户. pdbedit -x username:删除Samba账户. pdbedi ...

  5. .pnts点云

    一种3d tiles格式 MIME格式: <configuration> <system.webServer> <staticContent> <remove ...

  6. 用js实现登录的简单验证

    实现过程示意图 代码 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l ...

  7. python-unittest学习

    在说unittest之前,先说几个概念: TestCase 也就是测试用例 TestSuite 多个测试用例集合在一起,就是TestSuite TestLoader是用来加载TestCase到Test ...

  8. NGUI优化之Drawcall

    今天在运行之前的程序时,无意中发现一个简单的menu菜单页面drawcall居然达到接近30了,这个数值感觉太高了. 后网上查询关于降低drawcall的方法,发现主要有以下几点: 1.少用Panel ...

  9. 洛谷 P1296奶牛的耳语 题解

    题目传送门 这道题很显然可以用O(n2)的方法来做(记得排序),由于数据较水...但还是在for循环中加一些优化:++i,据说这样会快一些... #include<bits/stdc++.h&g ...

  10. 响应式之像素和viewport

    引言 按照pc尺寸做好的网页,在手机端打开,看起来像是pc的缩小版,东西都在只是字太小都看不清了,有什么办法放大呢? 于是去google一下,发现,贴了这么一行代码就轻松解决了: <meta n ...