树上莫队 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 < ...
随机推荐
- rsyslog 只读取变化的日志
<pre name="code" class="html">input(type="imfile" File="/us ...
- COJ 0244 HDNOIP201404最短路径
HDNOIP201404最短路径 难度级别: A: 编程语言:不限:运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 a.b.c是3个互不相等的1 ...
- JDBC远程从一个MySql数据库中的一张表里面读出数据(这个数据库需要用SSH隧道连接,大约8W条数据),然后分别插入到另一个数据库中的两张表里
package com.eeepay.lzj.db; import java.sql.Connection; import java.sql.Date; import java.sql.DriverM ...
- 2017年开年的第一次比较大的安全事件: MongoDB “赎金事件”,如何看待互联网安全问题
今天上午(2017年1月7日),我的微信群中同时出现了两个MongoDB被黑掉要赎金的情况,于是在调查过程中,发现了这个事件.这个事件应该是2017年开年的第一次比较大的安全事件吧,发现国内居然没有什 ...
- 聚聚科技---PHP开发笔试题及答案
1. echo(), print(), print_r()的区别? echo是PHP语言结构, print和print_r是函数.语言结构没有返回值,函数可以有返回值(即便没有用) . print( ...
- hibernate jpa 注解 @Temporal(TemporalType.DATE) 格式化时间日期,页面直接得到格式化类型的值
1.日期: @Temporal(TemporalType.DATE) @Column(name = "applyDate", nullable = false, length = ...
- 为什么要使用Nginx?
这里做了些基准测试表明nginx打败了其它的轻量级的web服务器和代理服务器,同样也赢了相对不是那么轻量级的产品. 有人说这些基准测试是不准确的,因为在这样那样的环境下,做的比较不一致.我倾向同意基准 ...
- [React Testing] Redux Reducers
Sometimes we want to test our Redux reducers to make sure they work as expected. In this lesson we w ...
- C# typeof Gettype is as &拆箱 装箱
有时候,我们不想用值类型的值,就是想用一个引用..Net提供了一个名为装箱(boxing)的机制,它允许根据值类型来创建一个对象,然后使用对这个新对象的一个引用. 首先,回顾两个重要的事实,1.对于引 ...
- C#实现测量程序运行时间及cpu使用时间
private void ShowRunTime() { TimeSpan ts1 = Process.GetCurrentProcess().TotalProcessorTime; Stopwatc ...