bzoj 3772
感觉做这种题收获很大。
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的更多相关文章
- bzoj 3772 :精神污染 线段树+打标记 or 主席树
3772: 精神污染 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 315 Solved: 87[Submit][Status][Discuss] D ...
- BZOJ 3772: 精神污染 (dfs序+树状数组)
跟 BZOJ 4009: [HNOI2015]接水果一样- CODE #include <set> #include <queue> #include <cctype&g ...
- 【BZOJ 3772】精神污染 主席树+欧拉序
这道题的内存…………………真·精神污染……….. 这道题的思路很明了,我们就是要找每一个路径包含了多少其他路径那么就是找,有多少路径的左右端点都在这条路径上,对于每一条路径,我们随便选定一个端点作为第 ...
- bzoj 3772 精神污染 主席树+dfs序
精神污染 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 637 Solved: 177[Submit][Status][Discuss] Descri ...
- BZOJ 3772: 精神污染(dfs序+主席树)
传送门 解题思路 比较神仙的一道题.首先计算答案时可以每条路径所包含的路径数,对于\(x,y\)这条路径,可以在\(x\)这处开个\(vector\)存\(y\),然后计算时只需要算这个路径上每个点的 ...
- BZOJ 2127: happiness [最小割]
2127: happiness Time Limit: 51 Sec Memory Limit: 259 MBSubmit: 1815 Solved: 878[Submit][Status][Di ...
- BZOJ 3275: Number
3275: Number Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 874 Solved: 371[Submit][Status][Discus ...
- BZOJ 2879: [Noi2012]美食节
2879: [Noi2012]美食节 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1834 Solved: 969[Submit][Status] ...
- bzoj 4610 Ceiling Functi
bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...
随机推荐
- Sublime text 3中文汉化教程
想弄个中文版的sublime,居然可以不用重新下载汉化包或者重新下载简体中文版了~而是只需要安装个插件即可! 工具/原料 电脑 sublime text3编辑器 方法/步骤 启动并进入s ...
- 记一个多线程使用libevent的问题
前段时间使用libevent网络库实现了一个游戏服务器引擎,在此记录下其中遇到的一个问题. 我在设计服务器上选择把逻辑和网络分线程,线程之间通信使用队列.但是这样做会有个问题: 当逻辑线程想要主动的发 ...
- 64_s1
SAASound-3.2-17.fc26.i686.rpm 13-Feb-2017 22:13 27650 SAASound-3.2-17.fc26.x86_64.rpm 13-Feb-2017 23 ...
- python之jsonpath的使用
import json import jsonpath import requests url="https://www.lagou.com/lbs/getAllCitySearchLabe ...
- NEERC2012
NEERC2012 A - Addictive Bubbles 题目描述:有一个\(n \times m\)的棋盘,还有不同颜色的棋子若干个,每次可以消去一个同种颜色的联通块,得到的分数为联通块中的棋 ...
- caffe Python API 之SoftmaxWithLoss
net.loss = caffe.layers.SoftmaxWithLoss(net.fc3, net.label) 输出: layer { name: "loss" type: ...
- 企业级-Mysql双主互备高可用负载均衡架构(基于GTID主从复制模式)(原创)
前言: 原理与思想 这里选用GTID主从复制模式Mysql主从复制模式,是为了更加确保主从复制的正确性.健康性与易配性.这里做的是两服务器A,B各有Mysql实例331 ...
- git rebase 过程中遇到冲突该怎么解决?
在执行git rebase 过程中经常遇到问题,此时有点慌,一般如何解决呢? 1.先将本地的冲突手动解决 2.执行下面命令 git add . git rebase --contine //继续re ...
- 【Mac】Chrome中添加截图扩展插件FireShot方法
FireShot是一款可以使用谷歌浏览器快速捕捉当前网页中元素的chrome截图插件,在谷歌浏览器中安装FireShot插件以后可以对网页中整个屏幕或者是网页的部分视图进行截图操作,在截图之后用户还可 ...
- webapi调用post时自动匹配参数
[HttpPost] public async Task<string> Post() { dynamic model = await Request.Content.ReadAsAsyn ...