树上莫队 wowow
构建:像线性的莫队那样,依旧是按sqrt(n)为一块分块。
int dfs(int x){
int size=;
dfn[x]=++ind;
for (int i=;i<=;i++)
if (bin[i]<=deep[x])
fa[x][i]=fa[fa[x][i-]][i-];
else break;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur!=fa[x][]){
fa[pur][]=x;
deep[pur]=deep[x]+;
size+=dfs(pur);
if (size>=blo){
blonum++;
for (int k=;k<=size;k++)
belong[st[top--]]=blonum;
size=;
}
}
}
st[++top]=x;
return size+;
}
然后呢,我们可以发现一些树上莫队的性质:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <vector>
#include <functional>
#include <ctime>
#include <cstdlib>
#include <sstream>
#include <set>
#include <deque>
#define Rep(i, l, r) for (int i = l; i <= r; ++i)
#define Req(i, l, r) for (int i = l; i >= r; --i)
#define N 100005
int tot,go[N],next[N],first[N],dfn[N],belong[N];
int st[N],res[N],n,m,x,y,fa[N][],bin[],col[N],ans,ind,deep[N],blo,blonum;
int top,pd[N],root;
struct op{
int u,v,id,a,b;
}q[N];
int p[N];
void insert(int x,int y){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
}
void add(int x,int y){
insert(x,y);
insert(y,x);
}
bool cmp(op q,op w){
if (belong[q.u]==belong[w.u]) return dfn[q.v]<dfn[w.v];
else return belong[q.u]<belong[w.u];
}
int dfs(int x){
int size=;
dfn[x]=++ind;
for (int i=;i<=;i++)
if (bin[i]<=deep[x])
fa[x][i]=fa[fa[x][i-]][i-];
else break;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur!=fa[x][]){
fa[pur][]=x;
deep[pur]=deep[x]+;
size+=dfs(pur);
if (size>=blo){
blonum++;
for (int k=;k<=size;k++)
belong[st[top--]]=blonum;
size=;
}
}
}
st[++top]=x;
return size+;
}
void reverse(int x){
if (pd[x]) {
p[col[x]]--;
pd[x]=;
if (p[col[x]]==) ans--;
}
else{
p[col[x]]++;
pd[x]=;
if (p[col[x]]==) ans++;
}
}
void solve(int u,int v){
while (u!=v){
if (deep[u]>deep[v]) reverse(u),u=fa[u][];
else reverse(v),v=fa[v][];
}
}
int lca(int x,int y){
if (deep[x]<deep[y]) std::swap(x,y);
int t=deep[x]-deep[y];
for (int i=;i>=;i--)
if (t&bin[i]){
x=fa[x][i];
}
for (int i=;i>=;i--)
if (fa[x][i]!=fa[y][i]){
x=fa[x][i];
y=fa[y][i];
}
if (x==y) return x;
else return fa[x][];
}
int main(){
bin[]=;
for (int i=;i<;i++) bin[i]=bin[i-]*;
scanf("%d%d",&n,&m);
blo=sqrt(n);
for (int i=;i<=n;i++)
scanf("%d",&col[i]);
for (int i=;i<=n;i++){
scanf("%d%d",&x,&y);
if (x==)
root=y;
else
if (y==)
root=x;
else
add(x,y);
}
dfs(root);
blonum++;
while (top) belong[st[top--]]=blonum;
for (int i=;i<=m;i++){
scanf("%d%d",&q[i].u,&q[i].v);
if (dfn[q[i].u]>dfn[q[i].v]) std::swap(q[i].v,q[i].u);
scanf("%d%d",&q[i].a,&q[i].b);
q[i].id=i;
}
std::sort(q+,q++m,cmp);
int t=lca(q[].u,q[].v);
solve(q[].u,q[].v);
reverse(t);
res[q[].id]=ans;
if (p[q[].a]&&p[q[].b]&&q[].a!=q[].b) res[q[].id]--;
reverse(t);
for (int i=;i<=m;i++){
solve(q[i-].u,q[i].u);
solve(q[i-].v,q[i].v);
t=lca(q[i].u,q[i].v);
reverse(t);
res[q[i].id]=ans;
if (p[q[i].a]&&p[q[i].b]&&q[i].a!=q[i].b) res[q[i].id]--;
reverse(t);
}
for (int i=;i<=m;i++)
printf("%d\n",res[i]);
}
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <vector>
#include <functional>
#include <ctime>
#include <cstdlib>
#include <sstream>
#include <set>
#include <deque>
#define Rep(i, l, r) for (int i = l; i <= r; ++i)
#define Req(i, l, r) for (int i = l; i >= r; --i)
#define N 200005
long long res[N];
long long pre[N],col[N],v[N],w[N],ans;
int belong[N],go[N],tot,first[N],next[N];
int deep[N],bin[],fa[N][],st[N],top,x,y,n,m,c1,c2,dfn[N],ind,blo,blonum;
int pd[N],p[N],qe,ty;
struct op{
int x,y,id,t;
long long pre;
}c[N],b[N];
bool cmp(op a,op b){
if (belong[a.x]==belong[b.x]&&belong[a.y]==belong[b.y]) return a.t<b.t;
else
if (belong[a.x]==belong[b.x]) return belong[a.y]<belong[b.y];
return belong[a.x]<belong[b.x];
}
void insert(int x,int y){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
}
void add(int x,int y){
insert(x,y);
insert(y,x);
}
int dfs(int x){
int size=;
dfn[x]=++ind;
for (int i=;i<=;i++)
if (deep[x]>=bin[i])
fa[x][i]=fa[fa[x][i-]][i-];
else break;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur!=fa[x][]){
fa[pur][]=x;
deep[pur]=deep[x]+;
size+=dfs(pur);
if (size>=blo){
blonum++;
for (int j=;j<=size;j++)
belong[st[top--]]=blonum;
size=;
}
}
}
st[++top]=x;
return size+;
}
void reverse(int x){
if (pd[x]){
ans-=w[p[col[x]]]*v[col[x]];
p[col[x]]--;
pd[x]=;
}
else{
pd[x]=;
p[col[x]]++;
ans+=w[p[col[x]]]*v[col[x]];
}
}
void change(int x,int y){
if (pd[x]){
reverse(x);
col[x]=y;
reverse(x);
}
else{
col[x]=y;
}
}
void solve(int x,int y){
while (x!=y){
if (deep[x]>deep[y]) reverse(x),x=fa[x][];
else reverse(y),y=fa[y][];
}
}
int lca(int x,int y){
if (deep[x]<deep[y]) std::swap(x,y);
int t=deep[x]-deep[y];
for (int i=;i>=;i--)
if (t&bin[i])
x=fa[x][i];
for (int i=;i>=;i--)
if (fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
if (x==y) return x;
else return fa[x][];
}
int main(){
//freopen("tx.txt","r",stdin);
bin[]=;
for (int i=;i<=;i++) bin[i]=bin[i-]*;
scanf("%d%d%d",&n,&m,&qe);
blo=pow(n,2.0/)*0.5;
for (int i=;i<=m;i++)
scanf("%lld",&v[i]);
for (int i=;i<=n;i++)
scanf("%lld",&w[i]);
for (int i=;i<n;i++){
scanf("%d%d",&x,&y);
add(x,y);
}
for (int i=;i<=n;i++){
scanf("%lld",&col[i]);
pre[i]=col[i];
}
dfs();
//blonum++;
while (top) belong[st[top--]]=blonum;
for (int i=;i<=qe;i++){
scanf("%d",&ty);
if (!ty){
c1++;
scanf("%d%d",&c[c1].x,&c[c1].y);
c[c1].pre=pre[c[c1].x];
pre[c[c1].x]=c[c1].y;
}
else{
c2++;
scanf("%d%d",&b[c2].x,&b[c2].y);
b[c2].t=c1;
if (dfn[b[c2].x]>dfn[b[c2].y]) std::swap(b[c2].x,b[c2].y);
b[c2].id=c2;
}
}
std::sort(b+,b++c2,cmp);
for (int i=;i<=b[].t;i++)
change(c[i].x,c[i].y);
solve(b[].x,b[].y);
int t=lca(b[].x,b[].y);
reverse(t);
res[b[].id]=ans;
reverse(t);
for (int i=;i<=c2;i++){
for (int j=b[i-].t+;j<=b[i].t;j++)
change(c[j].x,c[j].y);
for (int j=b[i-].t;j>b[i].t;j--)
change(c[j].x,c[j].pre);
solve(b[i-].x,b[i].x);
solve(b[i-].y,b[i].y);
int t=lca(b[i].x,b[i].y);
reverse(t);
res[b[i].id]=ans;
reverse(t);
}
for (int i=;i<=c2;i++)
printf("%lld\n",res[i]);
}
树上莫队 wowow的更多相关文章
- 【BZOJ 3735】苹果树 树上莫队(树分块+离线莫队+鬼畜的压行)
2016-05-09 UPD:学习了新的DFS序列分块,然后发现这个东西是战术核导弹?反正比下面的树分块不知道要快到哪里去了 #include<cmath> #include<cst ...
- 【BZOJ-3757】苹果树 块状树 + 树上莫队
3757: 苹果树 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1305 Solved: 503[Submit][Status][Discuss] ...
- [BZOJ 3052] [wc2013] 糖果公园 【树上莫队】
题目链接:BZOJ - 3052 题目分析 这道题就是非常经典的树上莫队了,并且是带修改的莫队. 带修改的莫队:将询问按照 左端点所在的块编号为第一关键字,右端点所在的块为第二关键字,位于第几次修改之 ...
- spoj COT2 - Count on a tree II 树上莫队
题目链接 http://codeforces.com/blog/entry/43230树上莫队从这里学的, 受益匪浅.. #include <iostream> #include < ...
- BZOJ 4129: Haruna’s Breakfast [树上莫队 分块]
传送门 题意: 单点修改,求一条链的mex 分块维护权值,$O(1)$修改$O(S)$求mex...... 带修改树上莫队 #include <iostream> #include < ...
- 【WC2013】糖果公园 [树上莫队]
题意: 一棵树,修改一个点的颜色,询问两点路径上每种颜色的权值$val[c]$*出现次数的权值$cou[w[c]]$的和 sro VFK 树上莫队 按照王室联邦的方法分块,块的大小直径个数有保证,并不 ...
- Codeforces 852I Dating 树上莫队
Dating 随便树上莫队搞一搞就好啦. #include<bits/stdc++.h> #define LL long long #define LD long double #defi ...
- 【XSY1642】Another Boring Problem 树上莫队
题目大意 给你一棵\(n\)个点的树,每个点有一个颜色\(c_i\),每次给你\(x,y,k\),求从\(x\)到\(y\)的路径上出现次数第\(k\)多的颜色的出现次数 \(n,q\leq 1000 ...
- SP10707 COT2 - Count on a tree II (树上莫队)
大概学了下树上莫队, 其实就是在欧拉序上跑莫队, 特判lca即可. #include <iostream> #include <algorithm> #include < ...
随机推荐
- http协议使用实例
#include <stdio.h>#include <windows.h>#include <wininet.h> #define MAXSIZE 1024#pr ...
- 基于HTML5 Canvas的饼状图表实现教程
昨天我们分享了一款基于HTML5的线性图表应用,效果非常不错,可以看在线DEMO或者实现教程.今天我们继续来分享一款基于HTML5的网页图表,它也是利用Canvas绘制的,但是和前面不同的是,这款图表 ...
- 算法导论(第三版)Problems2(归并插入排序、数列逆序计算)
讨论内容不说明,仅提供相应的程序. 2.1:归并插入排序θ(nlgn) void mergeInsertionSort(int a[], int l, int r, int k) { int m; & ...
- 【转】被误解的MVC和被神化的MVVM
被误解的MVC和被神化的MVVM 作者 唐巧 发布于 2015年11月2日 | ArchSummit全球架构师峰会(北京站)2016年12月02-03日举办 被误解的 MVC MVC 的历史 MV ...
- zabbix流量汇聚
"服务器流量汇总"领导提需求,要把几个数据中心的数据汇总起来,于是就google了一下"zabbix流量汇总" 按照其中一篇博客做了出来,博客地址如下. htt ...
- [原创+实战+钓鱼]setoolkit+映射
所需工具:setoolkit,花生壳 (此方法主要针对没有服务器,没有空间的攻击者.有服务器或者空间可以直接上传setoolkit的生成源码到服务器或者空间.) 1.setoolkit克隆一个站点 | ...
- 获取布局 ActionBar
LayoutInflater inflater = getLayoutInflater();View imageLayout = inflater.inflate(R.layout.preferenc ...
- hdu5067Harry And Dig Machine(TSP旅行商问题)
题目链接: huangjing 题意:给出一幅图.图中有一些点,然后从第1个点出发,然后途径全部有石头的点.最后回到原点,然后求最小距离.当初作比赛的时候不知道这就是旅行商经典问题.回来学了一下. 思 ...
- 关于ajax网络请求的封装
// 封装的ajax网络请求函数// obj 是一个对象function AJAX(obj){ //跨域请求 if (obj.dataType == "jsonp") ...
- 读取oracle页面或者进程卡住不动(死锁)
oracle最坑爹的地方:你insert update delete之后 或者kill死锁的时候记得一定要提交事务不然就是死锁卡在那里了 记住 kill死锁也是要提交事务的 select * ...