树上莫队的基本思路是把树按dfs序分块,然后先按x所在块从小到大排序,再按y所在块从小到大排序,处理询问即可。

这道题带修改,再加一个时间维即可。

设块大小为T,那么时间复杂度为$O(nT+\frac{n^3}{T^2})$,当$T=n^\frac23$时,时间复杂度最优,为$n^\frac53$.

但是实际测试中,取$T=n^\frac23*0.5$跑得比较快,还有询问中如果x所在块大于y所在块,就交换x,y,也可以加快速度。

在BZOJ上卡了两波评测机,BZOJ差点崩了..

#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std; typedef long long ll;
const int N=,M=;
int n,m,q,B,e,x,y,op,tt,t1,t2,tp,bl[N],st[N],v[N],w[N],a[N],_a[N],vs[N],g[N],f[N][],hd[N],d[N],nx[M],to[M];
ll aa,a1[N];
struct nd {
int x,y,t,id;
bool operator < (const nd &r) const {
return bl[x]==bl[r.x]?bl[y]==bl[r.y]?t<r.t:bl[y]<bl[r.y]:bl[x]<bl[r.x];
}
}b[N];
struct nd2 {int x,y,ls;}c[N];
void ad(int x,int y) {to[++e]=y,nx[e]=hd[x],hd[x]=e;}
int rd() {
int r=,c=getchar();
while(c<''||c>'') c=getchar();
while(c>=''&&c<='') r=r*+c-'',c=getchar();
return r;
} void dfs(int x) {
st[++tp]=x;
if(tp==B) {tt++; while(tp) bl[st[tp--]]=tt;}
for(int i=hd[x];i;i=nx[i]) if(!d[to[i]]) d[to[i]]=d[x]+,f[to[i]][]=x,dfs(to[i]);
}
int lca(int x,int y) {
if(d[x]<d[y]) swap(x,y);
for(int i=;~i;i--) if(d[f[x][i]]>=d[y]) x=f[x][i];
if(x==y) return x;
for(int i=;~i;i--) if(f[x][i]^f[y][i]) x=f[x][i],y=f[y][i];
return f[x][];
} void rv(int x) {
vs[x]^=;
if(vs[x]) aa+=(ll)v[a[x]]*w[++g[a[x]]]; else aa-=(ll)v[a[x]]*w[g[a[x]]--];
}
void gai(int x,int y) {if(vs[x]) rv(x),a[x]=y,rv(x); else a[x]=y;}
void rv(int x,int y) {
while(x^y) {
if(d[x]<d[y]) swap(x,y);
rv(x),x=f[x][];
}
} int main() {
scanf("%d%d%d",&n,&m,&q),B=pow(n,2.0/)*0.5;
for(int i=;i<=m;i++) v[i]=rd();
for(int i=;i<=n;i++) w[i]=rd();
for(int i=;i<n;i++) x=rd(),y=rd(),ad(x,y),ad(y,x);
for(int i=;i<=n;i++) a[i]=rd(),_a[i]=a[i];
d[]=,dfs(),tt++;
while(tp) bl[st[tp--]]=tt;
for(int j=;j<;j++)
for(int i=;i<=n;i++)
f[i][j]=f[f[i][j-]][j-];
for(int i=;i<=q;i++) {
op=rd(),x=rd(),y=rd();
if(op) {
if(bl[x]>bl[y]) swap(x,y);
b[++t1].x=x,b[t1].y=y,b[t1].t=t2,b[t1].id=t1;
}
else c[++t2].x=x,c[t2].y=y,c[t2].ls=_a[x],_a[x]=y;
}
sort(b+,b++t1),b[].x=b[].y=;
for(int i=,t=,k;i<=t1;i++) {
while(t<b[i].t) t++,gai(c[t].x,c[t].y);
while(t>b[i].t) gai(c[t].x,c[t].ls),t--;
rv(b[i].x,b[i-].x),rv(b[i].y,b[i-].y),rv(k=lca(b[i].x,b[i].y)),a1[b[i].id]=aa,rv(k);
}
for(int i=;i<=t1;i++) printf("%lld\n",a1[i]);
return ;
}

最新文章

  1. display:inline-block兼容ie6/7的写法
  2. 小菜鸟学 Spring-Dependency injection(二)
  3. 【阿里云产品公测】以开发者角度看ACE服务『ACE应用构建指南』
  4. 玩sdr的朋友们,在rtl_tcp时,记得调整rtl_AGC和tuner_AGC啊
  5. linux开机自动挂载NTFS-WINDOWS分区
  6. 对[yield]的浅究到发现[async][await]
  7. Android开发:组播(多播)与广播
  8. [.Net跨平台]部署DTCMS到Jexus遇到的问题及解决思路--验证码
  9. 我可能不懂Array.prototype.sort
  10. CentOS7+Hadoop2.7.2(HA高可用+Federation联邦)+Hive1.2.1+Spark2.1.0 完全分布式集群安装
  11. 【转】vue项目打包部署——nginx代理访问
  12. eHR自动同步获取LDAP中的邮箱地址
  13. String[]字符串数组,按字典顺序排列大小
  14. Android - AssetManager
  15. 【GIS】WGS84与Web墨卡托理解(转)
  16. No.16 selenium学习之路之异常处理
  17. JAVA中的protected(详解),以及和clone()方法有关的一些问题
  18. C#用 catch 捕获异类的常用类型
  19. Java学习---Pinyin4j使用手册
  20. IEEEXtreme 10.0 - Game of Stones

热门文章

  1. 201421123042 《Java程序设计》第14周学习总结
  2. Flask 扩展 HTTP认证
  3. Java8-如何构建一个Stream
  4. 前端双引号单引号,正则反向引用,js比较jq
  5. 第1章 什么是TCP-IP
  6. Linux CentOS7.0 (04)systemctl vs chkconfig、service
  7. SSM中的登陆验证码
  8. C#使用Gecko实现浏览器
  9. Zookeeper通过java创建、查看、修改、删除znode
  10. ZOJ-2913 Bus Pass---BFS进阶版