题意:给你一棵树,求u,v最短路径的XXX(本题是统计权值种类)

今天课上摸鱼学了一种有意思的处理路径方式(其实是链式块状树翻车了看别的),据说实际运行跑的比XX记者还快

大概就是像序列莫队那样

首先是对暴力查询的优化

第一关键字是块(树上分块),第二关键字是dfs序,这样保证了离线操作的下界最优

其次是转移的优化

我把大佬的话再转述一遍:

设\(S(u,v)\):\(u-v\)最短路径所覆盖的点集

\(S(u,v)=S(root,u)⊕S(root,v)⊕lca(u,v)\)

记\(T(u,v)=S(root,u)⊕S(root,v)\)

每次转移我们只考虑\(T\)的部分,\(lca\)单独处理

对于某一次距离为1的转移,如\(u→u'\)

\(T(u,u')=S(root,u)⊕S(root,u')\)

\(T(u',v)=S(root,u')⊕S(root,v)\)

\(T(u',v)=S(root,u)⊕S(root,v)⊕S(root,u)⊕S(root,u')=T(u,v)⊕T(u,u')\)

得出结论\(T(u',v)=T(u,v)⊕T(u,u')\)

就是说转移的时候只需多处理\(u-u'\)和\(v-v'\)即可(推广后就是任意距离都可以),记得考虑每次单独处理的\(lca\)(先后翻转2遍标记)

那么再经过%hzwer的帖子学习后得出可能正确的代码(由于无法交题,没有验证正确性)

#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define print(a) printf("%lld",(ll)(a))
#define println(a) printf("%lld\n",(ll)(a))
#define printbk(a) printf("%lld ",(ll)(a))
using namespace std;
const int MAXN = 3e4+11;
const int INF = 0x7fffffff;
typedef long long ll;
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int to[MAXN<<1],nxt[MAXN<<1],head[MAXN],tot;
void init(){
memset(head,-1,sizeof head);
tot=0;
}
void add(int u,int v){
to[tot]=v;
nxt[tot]=head[u];
head[u]=tot++;
}
int color[MAXN],belong[MAXN],depth[MAXN],dfn[MAXN];
int stk[MAXN],bit[32],limit,root,cnt,CLOCK,top;
int anc[MAXN][20];
bool vis[MAXN];
int ANS,cntNum[MAXN],ans[MAXN];
struct QQQ{
int u,v,a,b,id;
bool operator < (const QQQ &rhs) const{
if(belong[u]!=belong[rhs.u]){
return belong[u]<belong[rhs.u];
}else{
return dfn[v]<dfn[rhs.v];
}
}
}Q[MAXN]; int dfs(int u,int fa,int d){
dfn[u]=++CLOCK;
anc[u][0]=fa; depth[u]=d;
rep(i,1,16){
if(depth[u]<bit[i]) break;
anc[u][i]=anc[anc[u][i-1]][i-1];
}
int num=0;
erep(i,u){
int v=to[i];
if(v==fa) continue;
num+=dfs(v,u,d+1);
if(num>=limit){
++cnt;
rep(i,1,num) belong[stk[top--]]=cnt;
num=0;
}
}
stk[++top]=u; num++;
return num;
}
int lca(int u,int v){
if(depth[u]<depth[v]) swap(u,v);
int d=depth[u]-depth[v];
for(int i=0;bit[i]<=d;i++){
if(d>>i&1) u=anc[u][i];
}
for(int i=16;i>=0;i--){
if(anc[u][i]!=anc[v][i]){
u=anc[u][i];
v=anc[v][i];
}
}
if(u==v) return u;
else return anc[u][0];
}
void rev(int u){
if(!vis[u]){
vis[u]=1;
if(cntNum[color[u]]==0) ANS++;
cntNum[color[u]]++;
}else{
vis[u]=0;
if(cntNum[color[u]]==1) ANS--;
cntNum[color[u]]--;
}
}
void viss(int u,int v){
while(u!=v){
if(depth[u]>depth[v]) rev(u),u=anc[u][0];
else rev(v),v=anc[v][0];
}
}
int main(){
int n,m;
bit[0]=1;rep(i,1,30) bit[i]=bit[i-1]<<1;
while(cin>>n>>m){
init(); limit=sqrt(n)+1;
rep(i,1,n) color[i]=read();
rep(i,1,n){
int u=read();
int v=read();
if(u*v==0) root=u|v;
else add(u,v),add(v,u);
}
top=cnt=CLOCK=0;
memset(anc,0,sizeof anc);
dfs(root,0,1);
if(top){
cnt++;
while(top) belong[stk[top--]]=cnt;
}
rep(i,1,m){
Q[i].u=read();
Q[i].v=read();
Q[i].a=read();
Q[i].b=read();
Q[i].id=i;
}
sort(Q+1,Q+1+m); ANS=0;
int t=lca(Q[1].u,Q[1].v);
memset(vis,0,sizeof vis);
viss(Q[1].u,Q[1].v);
rev(lca(Q[1].u,Q[1].v));
ans[Q[1].id]=ANS;
rev(lca(Q[1].u,Q[1].v));
if(cntNum[Q[1].a]&&cntNum[Q[1].b]&&Q[1].a!=Q[1].b){
ans[Q[1].id]--;
}
rep(i,2,m){
viss(Q[i-1].u,Q[i].u);
viss(Q[i-1].v,Q[i].v);
rev(lca(Q[i].u,Q[i].v));
ans[Q[i].id]=ANS;
if(cntNum[Q[i].a]&&cntNum[Q[i].b]&&Q[i].a!=Q[i].b){
ans[Q[i].id]--;
}
rev(lca(Q[i].u,Q[i].v));
}
rep(i,1,m) println(ans[i]);
}
return 0;
}

BZOJ - 3757 树上莫队解决离线路径问题 & 学习心得的更多相关文章

  1. bzoj 3757 树上莫队

    感谢以下文章作者: http://blog.csdn.net/kuribohg/article/details/41458639 http://vfleaking.blog.163.com/blog/ ...

  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 3735】苹果树 树上莫队(树分块+离线莫队+鬼畜的压行)

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

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

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

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

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

  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. 「日常训练&知识学习」莫队算法(二):树上莫队(Count on a tree II,SPOJ COT2)

    题意与分析 题意是这样的,给定一颗节点有权值的树,然后给若干个询问,每次询问让你找出一条链上有多少个不同权值. 写这题之前要参看我的三个blog:Codeforces Round #326 Div. ...

随机推荐

  1. opennebula kvm 创建虚拟机错误

    Thu Jul :: : Error executing image transfer script: Error copying localhost.localdomain:/app/openneb ...

  2. 在Ubuntu上源码安装NodeJS

    Refer http://nqdeng.github.io/7-days-nodejs/#7.1 前提条件: 确保系统下g++版本(g++ -v)在4.6以上,python版本(python --ve ...

  3. 6.AND & OR 运算符

    AND 和 OR 运算符用于基于一个以上的条件对记录进行过滤 AND 和 OR 运算符 AND 和 OR 可在 WHERE 子语句中把两个或多个条件结合起来. 如果第一个条件和第二个条件都成立,则 A ...

  4. 利用osmosis导出osm城市数据

    转载(未测试) 方法核心就是利用osmosis的导出指定功能,即是从大范围导出小范围的基本用例. 我们只需要知道我们所需要提取的城市的经纬度范围, 例如广州市的经纬度范围是北纬22.26~23.56度 ...

  5. lnmp+laravel部署到服务器出现 "GET / HTTP/1.1" 500 5

    lnmp一键安装包直接下载安装,就可以了,在此不多说. 虚拟机配置给个参考(lnmp安装包) server { listen 80; #listen [::]:80; server_name www. ...

  6. (函数)实现strstr函数

    题目:实现strstr函数. 这个函数原型 strstr(char *a, char *b),在a中是否包含b这个字符串,包含返回第一个子串的位置,否则返回NULL. 思路:其实这个就是找子串的问题. ...

  7. 十一、Node.js监听代码改动自动重启node插件supervisor

    我们慢慢地发现,每次我们稍微改变js代码都需要重启服务才能在浏览器显示新的效果,很麻烦,这里我们可以通过npm命令安装supervisoror插件,安装方法如下 之前章节我们知道安装了nodejs就会 ...

  8. Windows10电脑系统时间校准

    有时候新安装电脑系统,系统时间不对,需要主动去校准系统时间. 1.点击时间 2.日期和时间设置 3.其他日期.时间和区域设置 4.设置时间和日期 5.Internet 时间 6.点击立即更新,如果更新 ...

  9. js去重方法

    function remove(array){ var obj={}; newarray=[]; for(var i in array){ console.log(i); var arg=array[ ...

  10. 【洛谷2113】看球泡妹子 DP背包

    看球泡妹子 题目背景 2014年巴西世界杯开幕了,现在满城皆是世界杯,商家们利用它大赚一笔,小明和小红也借此机会增进感情. 题目描述 本届世界杯共有\(N\)支球队,\(M\)场比赛.男球迷小明喜欢看 ...