bzoj 3757 树上莫队
感谢以下文章作者:
http://blog.csdn.net/kuribohg/article/details/41458639
http://vfleaking.blog.163.com/blog/static/174807634201311011201627/
http://blog.csdn.net/jiangyuze831/article/details/41476865
http://hzwer.com/5259.html
做了树上的莫队,感觉对这个算法的思想理解更深了
先分块,不论怎么分,要求同一块中的节点之间的距离不超过O(n0.5)
然后将图的DFS序搞出来
然后将询问(u,v),以u所在的块为第一关键字,以v在dfs序中的位置为第二关键字排序。
然后弄个初始状态,然后就在图上按照询问的顺序“爬”(从(u,v)的状态转移到(u',v'),细节见vfleaking文章)。
至于复杂度,和序列型莫队的分析是一样的,我们的时间开销主要花在“爬”上,我们将爬的开销分成两部分来算:
第一部分:(u,v)中u改变造成的开销,如果在同一块中转移,我们最多需要走O(n0.5)步,要走O(n)次;如果在块间转移,我们最多走O(n)步,要走O(n0.5)次。总的O(n1.5)
第二部分:(u,v)中v改变造成的开销,同一块中的所有点总的开销是O(n)(同一块中的v是按dfs序排的序),有O(n0.5)块,所以是O(n1.5);不同块间走O(n0.5)次,每次O(n),总的也是O(n1.5)
所以总的是O(n1.5)。
这题没说m的范围,开成和n一样要RE,记得开成它的两倍。
/**************************************************************
Problem: 3757
User: idy002
Language: C++
Result: Accepted
Time:17840 ms
Memory:16640 kb
****************************************************************/ #include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#define P(p) (1<<(p))
#define maxn 100010
#define maxp 15
using namespace std; int n, m;
int root;
vector<int> g[maxn];
int stat[maxn], clr[maxn], cnt[maxn], clr_tot;
int anc[maxn][maxp+], depth[maxn], dfn[maxn], dfs_clock;
int mccno[maxn], mcc_len, mcc_tot;
int ans[maxn]; struct Qu {
int u, v, id;
int a, b;
bool operator<( const Qu & c ) const {
return mccno[u]<mccno[c.u] || ( mccno[u]==mccno[c.u] && dfn[v]<dfn[c.v] );
}
};
Qu qry[maxn]; void dfs( int u, int fa, vector<int> &remain ) {
dfn[u] = ++dfs_clock;
anc[u][] = fa;
for( int p=; p<=maxp; p++ )
anc[u][p] = anc[anc[u][p-]][p-];
depth[u] = depth[fa]+;
vector<int> cur;
for( int t=; t<g[u].size(); t++ ) {
int v = g[u][t];
if( v==fa ) continue;
dfs(v,u,cur);
if( cur.size()>mcc_len ) {
mcc_tot++;
while( !cur.empty() ) {
mccno[ cur.back() ] = mcc_tot;
cur.pop_back();
}
}
}
while( !cur.empty() ) {
remain.push_back( cur.back() );
cur.pop_back();
}
remain.push_back(u);
} int lca( int u, int v ) {
if( depth[u]<depth[v] ) swap(u,v);
int t = depth[u]-depth[v];
for( int p=maxp; p>= && t; p-- )
if( t&(P(p)) ) u = anc[u][p];
if( u==v ) return u;
for( int p=maxp; p>= && anc[u][]!=anc[v][]; p-- )
if( anc[u][p]!=anc[v][p] ) u = anc[u][p], v = anc[v][p];
return anc[u][];
} void inv_sig( int u ) {
int c = clr[u];
int d = stat[u] ? - : ;
stat[u] ^= ;
if( cnt[c]== ) clr_tot++;
cnt[c] += d;
if( cnt[c]== ) clr_tot--;
}
void inverse( int u, int v ) { // inverse T(u,v)
int ca = lca(u,v);
for( ; u!=ca; u=anc[u][] )
inv_sig(u);
for( ; v!=ca; v=anc[v][] )
inv_sig(v);
}
void calc( int q ) {
inverse( qry[q-].u, qry[q].u );
inverse( qry[q-].v, qry[q].v );
int ca = lca( qry[q].u, qry[q].v ); inv_sig( ca );
ans[qry[q].id] = clr_tot;
if( qry[q].a != qry[q].b && cnt[qry[q].a] && cnt[qry[q].b] )
ans[qry[q].id]--;
inv_sig( ca );
} int main() {
scanf( "%d%d", &n, &m );
mcc_len = (int)sqrt(n+);
for( int i=; i<=n; i++ )
scanf( "%d", clr+i );
for( int i=,u,v; i<=n; i++ ) {
scanf( "%d%d", &u, &v );
if( u== ) root=v;
if( v== ) root=u;
if( u&&v ) {
g[u].push_back( v );
g[v].push_back( u );
}
}
for( int i=; i<=m; i++ ) {
scanf( "%d%d%d%d", &qry[i].u, &qry[i].v, &qry[i].a, &qry[i].b );
qry[i].id = i;
} vector<int> remain;
dfs( root, root, remain );
while( remain.size() ) {
mccno[ remain.back() ] = mcc_tot;
remain.pop_back();
} sort( qry+, qry++m ); qry[].u = qry[].v = qry[].u;
for( int i=; i<=m; i++ )
calc(i);
for( int i=; i<=m; i++ )
printf( "%d\n", ans[i] );
}
(代码巨慢,应该是分块时拖下来的)
bzoj 3757 树上莫队的更多相关文章
- BZOJ - 3757 树上莫队解决离线路径问题 & 学习心得
题意:给你一棵树,求u,v最短路径的XXX(本题是统计权值种类) 今天课上摸鱼学了一种有意思的处理路径方式(其实是链式块状树翻车了看别的),据说实际运行跑的比XX记者还快 大概就是像序列莫队那样 首先 ...
- BZOJ 3757 苹果树 ——莫队算法
挺好的一道题目,怎么就没有版权了呢?大数据拍过了,精神AC.... 发现几种颜色这性质比较垃圾,不可加,莫队硬上. %了一发popoqqq大神的博客, 看了一波VFK关于糖果公园的博客, 又找了wjm ...
- bzoj 3052 树上莫队 待修改
感谢: http://vfleaking.blog.163.com/blog/static/174807634201311011201627/ http://hzwer.com/5250.html 好 ...
- [BZOJ 3052] [wc2013] 糖果公园 【树上莫队】
题目链接:BZOJ - 3052 题目分析 这道题就是非常经典的树上莫队了,并且是带修改的莫队. 带修改的莫队:将询问按照 左端点所在的块编号为第一关键字,右端点所在的块为第二关键字,位于第几次修改之 ...
- BZOJ.3052.[WC2013]糖果公园(树上莫队 带修改莫队)
题目链接 BZOJ 当然哪都能交(都比在BZOJ交好),比如UOJ #58 //67376kb 27280ms //树上莫队+带修改莫队 模板题 #include <cmath> #inc ...
- 【BZOJ 3735】苹果树 树上莫队(树分块+离线莫队+鬼畜的压行)
2016-05-09 UPD:学习了新的DFS序列分块,然后发现这个东西是战术核导弹?反正比下面的树分块不知道要快到哪里去了 #include<cmath> #include<cst ...
- BZOJ 4129: Haruna’s Breakfast [树上莫队 分块]
传送门 题意: 单点修改,求一条链的mex 分块维护权值,$O(1)$修改$O(S)$求mex...... 带修改树上莫队 #include <iostream> #include < ...
- 【BZOJ-3757】苹果树 块状树 + 树上莫队
3757: 苹果树 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1305 Solved: 503[Submit][Status][Discuss] ...
- 【BZOJ4129】Haruna’s Breakfast(树上莫队)
[BZOJ4129]Haruna's Breakfast(树上莫队) 题面 BZOJ Description Haruna每天都会给提督做早餐! 这天她发现早饭的食材被调皮的 Shimakaze放到了 ...
随机推荐
- 20、什么样的项目适合Web自动化测试
1.什么是Web自动化测试?概念:让程序代替人为自动验证Web项目功能的过程 2.什么Web项目适合做自动化测试 1.需求变动不频繁 2.项目周期长 3.项目需要回归测试 3.如阿进行Web自动化测试 ...
- scrapy 爬虫踩过的坑(I)
问题1:正则表达式没问题,但是爬虫进不了item方法 分析: 1. 可能是下载不到list 页面的内容.可以用 scrapy shell url 进行测试 2. 可能是allowed_domains ...
- document.write 简介
document.write 的执行分两种情况: 第一种:dom加载已完成 1. 执行 document.open() (即会清空document) 2. 执行 document.write() 3. ...
- css的背景图片background
1.使用背景图片的标签定设置宽高,没有设置的话,也需要用内容来撑开标签. 2.如果对同一个标签分开设置背景图片和颜色,背景颜色一定要写在背景图片后面,不然会被覆盖 <!DOCTYPE html& ...
- C/++——C语言备忘录
1. static变量初始化 在C中,由static修饰的静态变量在没有显式初始化时,将会被初始化为0(对于指针是NULL) 参考:https://en.wikipedia.org/wiki/Unin ...
- 浅谈Java中的hashcode方法(转)
原文链接:http://www.cnblogs.com/dolphin0520/p/3681042.html 浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地 ...
- Activity工作流 -- java运用
一. 什么是工作流 以请假为例,现在大多数公司的请假流程是这样的 员工打电话(或网聊)向上级提出请假申请——上级口头同意——上级将请假记录下来——月底将请假记录上交公司——公司将请假录入电脑 采用工作 ...
- 让Linux应用更加得心应手的
1.计算文件数和目录数 下面的语句可以帮你计算有多少个文件和多少个目录 # ls -l * |grep "^-"|wc -l ---- to count files # ls - ...
- Retrofit:类型安全的REST客户端for 安卓&Java
Retrofit:类型安全的REST客户端for 安卓&Java 2014年5月5日 星期一 21:11 官网: http://square.github.io/retrofit/ GitH ...
- hdu 4726(贪心)
Kia's Calculation Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others ...