【JZOJ 4503】 异或树 动态点分治
2016-06-12 20:13
288 查看
Description
这只熊孩子会搞T次破坏,点权为Ei。
对于100%的数据2<=n,T<=30000,Ei<=16384
Analysis
Ei<=16384=214,这启示了我们什么?xor怎么解决?可以拆位做,最后每个二进制位合并。
这题如果不搞破坏,点分治可做。
可是搞破坏,难道要打动态点分治?
没错!
首先把修改操作拆成位数个,对于该位0改成1,就加上0的点的权值减去1的点的权值。
但是怎么算任意点到该点的权值和?
把我们上面点分治的分治树copy下来,每次往父节点跳,对于当前点,算出它的兄弟点到它的权值和。当然最开始要算上它的子树到它的权值和。因为分治树的深度是log2n的,所以单次询问的复杂度是O(log2n)的。
一个小细节,分治树上的父子关系可能与原树上的不同,所以两点间距离要用原树上dis[u]+dis[v]-2*dis[lca]来解决。HowarLi貌似有一种高级的方法不用lca。
具体实现繁(wei)琐(suo),若有做此题的欲望应做好心理准备(本蒟蒻被虐了一周)。
Code
代码比较长。而且垫底了,so sad#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) #define fd(i,b,a) for(int i=b;i>=a;i--) #define efo(i,u) for(int i=last[u];i;i=next[i]) using namespace std; typedef long long ll; const int N=30010,M=N*2; int n,m,tot,val,num,rt,root,to[M],next[M],wei[M],last ; int f [16],dep ,dis ,fa ,size ,sum [2]; ll ans,a ; struct node { ll dis,s,a,id; }b ,c ; struct lyd { ll s0,n0,fs; }sm [15][2]; bool bz ; void link(int u,int v,int w) { to[++tot]=v,wei[tot]=w,next[tot]=last[u],last[u]=tot; } void dfs1(int v,int from,int d,int k) { f[v][0]=from,dep[v]=d,dis[v]=k; efo(i,v) { int u=to[i]; if(u==from) continue; dfs1(u,v,d+1,k+wei[i]); } } int lca(int u,int v) { if(dep[u]<dep[v]) swap(u,v); fd(i,int(log2(dep[u])),0) if(dep[f[u][i]]>=dep[v]) u=f[u][i]; fd(i,int(log2(dep[u])),0) if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i]; if(u!=v) return f[u][0]; return u; } ll dist(int x,int y) { return dis[x]+dis[y]-2*dis[lca(x,y)]; } void getrt(int v,int from,int num) { size[v]=1; int x=0; efo(i,v) { int u=to[i]; if(u==from || bz[u]) continue; getrt(u,v,num); x=max(x,size[u]); size[v]+=size[u]; } int mx=max(x,num-size[v]); if(mx<val) val=mx,rt=v; } void dfs(int v,int from,int S,int k) { b[++m].s=S,b[m].dis=k,b[m].a=a[v],b[m].id=v; efo(i,v) { int u=to[i]; if(u==from || bz[u]) continue; dfs(u,v,S,k+wei[i]); } } void divide(int v,int from,int num) { val=2147483647; getrt(v,from,num); fa[rt]=from; if(!root) root=rt,fa[root]=root; int rt1=rt; m=0; efo(i,rt) { int u=to[i]; if(u==from || bz[u]) continue; dfs(u,rt,u,wei[i]); } fo(i,1,m) ans+=(b[i].a^a[rt])*b[i].dis; fo(j,0,14) { int c1=0; ll s0=0,n0=0,t=0; sm[rt][j][(a[rt]&(1<<j))>=1].n0=1; sm[rt][j][(a[rt]&(1<<j))>=1].fs+=dist(rt,fa[rt]); fo(i,1,m) { bool p=(b[i].a&(1<<j))>=1; sm[rt][j][p].n0++,sm[rt][j][p].s0+=b[i].dis; sm[rt][j][p].fs+=dist(fa[rt],b[i].id); if(p) c[++c1]=b[i]; else { s0+=b[i].dis,n0++; sum[b[i].s][0]+=b[i].dis,sum[b[i].s][1]++; } } fo(i,1,c1) t+=c[i].dis*(n0-sum[c[i].s][1])+s0-sum[c[i].s][0]; fo(i,1,m) sum[b[i].s][0]=sum[b[i].s][1]=0; ans+=t*(1<<j); } bz[rt]=1; efo(i,rt1) { int u=to[i]; if(u==from || bz[u]) continue; divide(u,rt1,size[u]); } } ll change(int v,int x,bool bz) { ll t=sm[v][x][bz].s0-sm[v][x][1-bz].s0,s0,n0,len; for(int u=v;;u=fa[u]) { if(u==root) break; len=dist(v,fa[u]); s0=sm[fa[u]][x][bz].s0-sm[u][x][bz].fs; n0=sm[fa[u]][x][bz].n0-sm[u][x][bz].n0; t+=s0+n0*len; s0=sm[fa[u]][x][1-bz].s0-sm[u][x][1-bz].fs; n0=sm[fa[u]][x][1-bz].n0-sm[u][x][1-bz].n0; t-=s0+n0*len; } for(int u=v;;u=fa[u]) { sm[u][x][1-bz].n0++,sm[u][x][bz].n0--; if(u==root) break; len=dist(v,fa[u]); sm[u][x][1-bz].fs+=len,sm[u][x][bz].fs-=len; sm[fa[u]][x][1-bz].s0+=len,sm[fa[u]][x][bz].s0-=len; } return t; } int main() { int _,u,v,w; scanf("%d",&n); fo(i,1,n) scanf("%d",&a[i]); fo(i,1,n-1) { scanf("%d %d %d",&u,&v,&w); link(u,v,w),link(v,u,w); } dfs1(1,1,1,0); fo(j,1,int(log2(n))) fo(i,1,n) f[i][j]=f[f[i][j-1]][j-1]; divide(1,0,n); scanf("%d",&_); while(_--) { scanf("%d %d",&v,&w); fo(i,0,14) if((a[v]^w)&(1<<i)) ans+=(1<<i)*change(v,i,a[v]&(1<<i)); a[v]=w; printf("%lld\n",ans); } return 0; }
相关文章推荐
- ListView 应用Demo-使用ArrayAdapter
- eclipse安装swing插件
- Android 5种存储方式
- wamp集成环境修改mysql的默认编码格式
- iOS安全系列之 HTTPS 进阶
- ASP.NET 4.5.256 尚未在Web服务器上注册。
- post 相比get 有很多优点,为什么现在的HTTP通信中大多数请求还是使用get?
- UML建模
- 数据库中行列转换
- 油猴脚本(tampermonkey)推荐与下载
- Heap与stack const关键字的作用。
- 迦瓦栈队 团队第五周项目总结
- Java组合和继承的区别
- 多线程——NSOperation
- php正则匹配大全
- Class.isAssignableFrom(Class clz)方法 与 instanceof 关键字的区别
- 视觉SLAM中的数学基础 第四篇 李群与李代数(2)
- 数据库快照的建立,并使用它恢复原数据库
- Google体系地图纠偏算法
- aaaaaaaaaaaaaaaaaaaaaaa