感谢以下文章作者:

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 树上莫队的更多相关文章

  1. BZOJ - 3757 树上莫队解决离线路径问题 & 学习心得

    题意:给你一棵树,求u,v最短路径的XXX(本题是统计权值种类) 今天课上摸鱼学了一种有意思的处理路径方式(其实是链式块状树翻车了看别的),据说实际运行跑的比XX记者还快 大概就是像序列莫队那样 首先 ...

  2. BZOJ 3757 苹果树 ——莫队算法

    挺好的一道题目,怎么就没有版权了呢?大数据拍过了,精神AC.... 发现几种颜色这性质比较垃圾,不可加,莫队硬上. %了一发popoqqq大神的博客, 看了一波VFK关于糖果公园的博客, 又找了wjm ...

  3. bzoj 3052 树上莫队 待修改

    感谢: http://vfleaking.blog.163.com/blog/static/174807634201311011201627/ http://hzwer.com/5250.html 好 ...

  4. [BZOJ 3052] [wc2013] 糖果公园 【树上莫队】

    题目链接:BZOJ - 3052 题目分析 这道题就是非常经典的树上莫队了,并且是带修改的莫队. 带修改的莫队:将询问按照 左端点所在的块编号为第一关键字,右端点所在的块为第二关键字,位于第几次修改之 ...

  5. BZOJ.3052.[WC2013]糖果公园(树上莫队 带修改莫队)

    题目链接 BZOJ 当然哪都能交(都比在BZOJ交好),比如UOJ #58 //67376kb 27280ms //树上莫队+带修改莫队 模板题 #include <cmath> #inc ...

  6. 【BZOJ 3735】苹果树 树上莫队(树分块+离线莫队+鬼畜的压行)

    2016-05-09 UPD:学习了新的DFS序列分块,然后发现这个东西是战术核导弹?反正比下面的树分块不知道要快到哪里去了 #include<cmath> #include<cst ...

  7. BZOJ 4129: Haruna’s Breakfast [树上莫队 分块]

    传送门 题意: 单点修改,求一条链的mex 分块维护权值,$O(1)$修改$O(S)$求mex...... 带修改树上莫队 #include <iostream> #include < ...

  8. 【BZOJ-3757】苹果树 块状树 + 树上莫队

    3757: 苹果树 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1305  Solved: 503[Submit][Status][Discuss] ...

  9. 【BZOJ4129】Haruna’s Breakfast(树上莫队)

    [BZOJ4129]Haruna's Breakfast(树上莫队) 题面 BZOJ Description Haruna每天都会给提督做早餐! 这天她发现早饭的食材被调皮的 Shimakaze放到了 ...

随机推荐

  1. N-gram语言模型与马尔科夫假设关系(转)

    1.从独立性假设到联合概率链朴素贝叶斯中使用的独立性假设为 P(x1,x2,x3,...,xn)=P(x1)P(x2)P(x3)...P(xn) 去掉独立性假设,有下面这个恒等式,即联合概率链规则 P ...

  2. DataFrame衍生新特征操作

    1.DataFrame中某一列的值衍生为新的特征 #将LBL1特征的值衍生为one-hot形式的新特征 piao=df_train_log.LBL1.value_counts().index #先构造 ...

  3. perl6 一个猜测密码的注入

    use HTTP::UserAgent; my $ua = HTTP::UserAgent.new; my $r = HTTP::Request.new; my $c = HTTP::Cookies. ...

  4. elk系列8之logstash+redis+es的架构来收集apache的日志【转】

    preface logstash--> redis --> logstash --> es这套架构在讲究松耦合关系里面是最简单的,架构图如下: 解释下这个架构图的流程 首先前端log ...

  5. SyntaxError: Missing parentheses in call to 'print' 这个错误原因是Python版本问题

    问题 print "www.baidu.com"           Python2 print ("www.baidu.com")     Python3 出 ...

  6. Linux系统调优及安全设置

    1.关闭SELinux #临时关闭 setenforce 0 #永久关闭 vim /etc/selinux/config SELINUX=disabled 2.设定运行级别为3 #设定运行级别 vim ...

  7. Maven核心概念

    一.坐标 在平面几何中,坐标(x,y)可以标识平面中唯一的一个点.在maven中,坐标是为了定位一个唯一确定的jar包.Maven世界拥有大量构建,我们需要找一个用来唯一标识一个构建的统一规范:拥有了 ...

  8. [ python ] 初始面向对象

    首先,通过之前学习的函数编写一个 人狗大战 的例子. 分析下这个需求,人 狗 大战  三个事情.角色:人.狗动作:狗咬人,人打狗 先创建人和狗两个角色: def person(name, hp, ag ...

  9. day01作业

    Java技术按照用途不同分为三大版本,分别是JavaSE.JavaEE和JavaMeJava虚拟机就是一个虚拟的用于执行字节码文件的计算机.它是Java最核心的技术,是Java跨平台的基础.DOS命令 ...

  10. 主机名/etc/hosts文件的作用

    1,/etc/hosts,主机名ip配置文件. # Do not remove the following line, or various programs # that require netwo ...