bzoj千题计划244:bzoj3730: 震波
http://www.lydsy.com/JudgeOnline/problem.php?id=3730
点分树内对每个节点动态维护2颗线段树
线段树以距离为下标,城市的价值为权值
对于节点x的两棵线段树:
一棵维护 点分树中,x的子树 的贡献
一棵维护 点分树中,x对x的父节点的贡献
查询和修改时,暴力往上爬点分树
点分树保证了最多往上爬log次
查询x k时,先加上点分树内,x的子树中距离<=k的权值和,
再爬到x的父节点f,若x和f的距离为d,则加上f的子树中距离<=k-d的权值和,还要减去 x对f 贡献的<=k-d的权值和,因为这一部分在之前x的子树中算过了
以此类推 ,这就是第二棵线段树的作用
常数优化:
原代码总耗时:20.105 s
#include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; #define N 100001 int n,a[N]; int front[N],nxt[N<<],to[N<<],tot; int all,root;
int siz[N],f[N]; bool vis[N]; int dep[N];
int fa[N][],dis[N][]; struct Segment
{
int cnt;
int rt[N];
int lc[N*],rc[N*],val[N*]; void Change(int &k,int l,int r,int x,int y)
{
if(!k) k=++cnt;
if(l==r)
{
val[k]+=y;
return;
}
int mid=l+r>>;
if(x<=mid) Change(lc[k],l,mid,x,y);
else Change(rc[k],mid+,r,x,y);
val[k]=val[lc[k]]+val[rc[k]];
} int Query(int k,int l,int r,int x)
{
if(!k) return ;
if(r<=x) return val[k];
int mid=l+r>>;
if(x<=mid) return Query(lc[k],l,mid,x);
else return val[lc[k]]+Query(rc[k],mid+,r,x);
} }tr,ftr; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
} void getroot(int x,int y)
{
siz[x]=; f[x]=;
for(int i=front[x];i;i=nxt[i])
if(to[i]!=y && !vis[to[i]])
{
getroot(to[i],x);
siz[x]+=siz[to[i]];
f[x]=max(f[x],siz[to[i]]);
}
f[x]=max(f[x],all-siz[x]);
if(f[x]<f[root]) root=x;
} void cal(int x,int ancestor,int father,int d)
{
int t;
for(int i=front[x];i;i=nxt[i])
{
t=to[i];
if(t!=father && !vis[t])
{
fa[t][++dep[t]]=ancestor;
dis[t][dep[t]]=d+;
cal(t,ancestor,x,d+);
}
}
} void build(int x)
{
vis[x]=true;
cal(x,x,,);
int tmp=all;
for(int i=front[x];i;i=nxt[i])
if(!vis[to[i]])
{
all=siz[to[i]];
if(all>siz[x]) all=tmp-siz[x];
root=;
getroot(to[i],);
build(root);
}
} void change(int x,int y)
{
tr.Change(tr.rt[x],,n-,,y);
int d;
for(int i=dep[x];i;--i)
{
ftr.Change(ftr.rt[fa[x][i+]],,n-,dis[x][i],y);
// printf("kk %d\n",dis[x][i]);
tr.Change(tr.rt[fa[x][i]],,n-,dis[x][i],y);
}
} int query(int x,int d)
{
int ans=tr.Query(tr.rt[x],,n-,d);
for(int i=dep[x];i;--i)
{
if(d-dis[x][i]>=) ans+=tr.Query(tr.rt[fa[x][i]],,n-,d-dis[x][i]);
if(d-dis[x][i]>=) ans-=ftr.Query(ftr.rt[fa[x][i+]],,n-,d-dis[x][i]);
}
return ans;
} void out(int x)
{
if(x>=) out(x/);
putchar(x%+'');
} int main()
{
freopen("wave.in","r",stdin);
freopen("wave.out","w",stdout);
int size = << ; // 256MB
char *p = (char*)malloc(size) + size;
__asm__("movl %0, %%esp\n" :: "r"(p));
int m;
read(n); read(m);
for(int i=;i<=n;++i) read(a[i]);
int u,v;
for(int i=;i<n;++i)
{
read(u); read(v);
add(u,v);
}
f[]=n+;
all=n;
getroot(,);
build(root);
for(int i=;i<=n;++i) fa[i][dep[i]+]=i;
for(int i=;i<=n;++i)
change(i,a[i]);
int ty,last=;
while(m--)
{
read(ty); read(u); read(v);
u^=last; v^=last;
if(!ty) last=query(u,v),out(last),printf("\n");
else change(u,v-a[u]),a[u]=v;
}
//printf("%d %d",tr.cnt,ftr.cnt);
return ;
}
原代码
1、原本线段树的操作封装在结构体里,拿出来,总耗时:16.934 s
2、动态开节点线段树 单点加:

在寻找x的路径上就进行加操作,而不是找到后再update
总耗时:14.357 s
3、数组改成结构体 总耗时:12.684 s
#include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; #define N 100001 int n,a[N]; int front[N],nxt[N<<],to[N<<],tot; int all,root;
int siz[N],f[N]; bool vis[N]; int dep[N];
int fa[N][],dis[N][]; int rt[N<<],cnt; struct node
{
int lc,rc,val;
}tr[N*]; void Change(int &k,int l,int r,int x,int y)
{
if(!k) k=++cnt;
tr[k].val+=y;
if(l==r) return;
int mid=l+r>>;
if(x<=mid) Change(tr[k].lc,l,mid,x,y);
else Change(tr[k].rc,mid+,r,x,y); } int Query(int k,int l,int r,int x)
{
if(!k) return ;
if(r<=x) return tr[k].val;
int mid=l+r>>;
if(x<=mid) return Query(tr[k].lc,l,mid,x);
else return tr[tr[k].lc].val+Query(tr[k].rc,mid+,r,x);
} void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot;
to[++tot]=u; nxt[tot]=front[v]; front[v]=tot;
} void getroot(int x,int y)
{
siz[x]=; f[x]=;
for(int i=front[x];i;i=nxt[i])
if(to[i]!=y && !vis[to[i]])
{
getroot(to[i],x);
siz[x]+=siz[to[i]];
f[x]=max(f[x],siz[to[i]]);
}
f[x]=max(f[x],all-siz[x]);
if(f[x]<f[root]) root=x;
} void cal(int x,int ancestor,int father,int d)
{
int t;
for(int i=front[x];i;i=nxt[i])
{
t=to[i];
if(t!=father && !vis[t])
{
fa[t][++dep[t]]=ancestor;
dis[t][dep[t]]=d+;
cal(t,ancestor,x,d+);
}
}
} void build(int x)
{
vis[x]=true;
cal(x,x,,);
int tmp=all;
for(int i=front[x];i;i=nxt[i])
if(!vis[to[i]])
{
all=siz[to[i]];
if(all>siz[x]) all=tmp-siz[x];
root=;
getroot(to[i],);
build(root);
}
} void change(int x,int y)
{
Change(rt[x],,n-,,y);
int d;
for(int i=dep[x];i;--i)
{
Change(rt[fa[x][i+]+n],,n-,dis[x][i],y);
// printf("kk %d\n",dis[x][i]);
Change(rt[fa[x][i]],,n-,dis[x][i],y);
}
} int query(int x,int d)
{
int ans=Query(rt[x],,n-,d);
for(int i=dep[x];i;--i)
{
if(d-dis[x][i]>=) ans+=Query(rt[fa[x][i]],,n-,d-dis[x][i]);
if(d-dis[x][i]>=) ans-=Query(rt[fa[x][i+]+n],,n-,d-dis[x][i]);
}
return ans;
} void out(int x)
{
if(x>=) out(x/);
putchar(x%+'');
} int main()
{
int m;
read(n); read(m);
for(int i=;i<=n;++i) read(a[i]);
int u,v;
for(int i=;i<n;++i)
{
read(u); read(v);
add(u,v);
}
f[]=n+;
all=n;
getroot(,);
build(root);
for(int i=;i<=n;++i) fa[i][dep[i]+]=i;
for(int i=;i<=n;++i)
change(i,a[i]);
int ty,last=;
while(m--)
{
read(ty); read(u); read(v);
u^=last; v^=last;
if(!ty) last=query(u,v),out(last),printf("\n");
else change(u,v-a[u]),a[u]=v;
}
//printf("%d %d",tr.cnt,ftr.cnt);
return ;
}
bzoj千题计划244:bzoj3730: 震波的更多相关文章
- bzoj千题计划300:bzoj4823: [Cqoi2017]老C的方块
http://www.lydsy.com/JudgeOnline/problem.php?id=4823 讨厌的形状就是四联通图 且左右各连一个方块 那么破坏所有满足条件的四联通就好了 按上图方式染色 ...
- bzoj千题计划196:bzoj4826: [Hnoi2017]影魔
http://www.lydsy.com/JudgeOnline/problem.php?id=4826 吐槽一下bzoj这道题的排版是真丑... 我还是粘洛谷的题面吧... 提供p1的攻击力:i,j ...
- bzoj千题计划280:bzoj4592: [Shoi2015]脑洞治疗仪
http://www.lydsy.com/JudgeOnline/problem.php?id=4592 注意操作1 先挖再补,就是补的范围可以包含挖的范围 SHOI2015 的题 略水啊(逃) #i ...
- bzoj千题计划177:bzoj1858: [Scoi2010]序列操作
http://www.lydsy.com/JudgeOnline/problem.php?id=1858 2018 自己写的第1题,一遍过 ^_^ 元旦快乐 #include<cstdio> ...
- bzoj千题计划317:bzoj4650: [Noi2016]优秀的拆分(后缀数组+差分)
https://www.lydsy.com/JudgeOnline/problem.php?id=4650 如果能够预处理出 suf[i] 以i结尾的形式为AA的子串个数 pre[i] 以i开头的形式 ...
- bzoj千题计划304:bzoj3676: [Apio2014]回文串(回文自动机)
https://www.lydsy.com/JudgeOnline/problem.php?id=3676 回文自动机模板题 4年前的APIO如今竟沦为模板,,,╮(╯▽╰)╭,唉 #include& ...
- bzoj千题计划292:bzoj2244: [SDOI2011]拦截导弹
http://www.lydsy.com/JudgeOnline/problem.php?id=2244 每枚导弹成功拦截的概率 = 包含它的最长上升子序列个数/最长上升子序列总个数 pre_len ...
- bzoj千题计划278:bzoj4590: [Shoi2015]自动刷题机
http://www.lydsy.com/JudgeOnline/problem.php?id=4590 二分 这么道水题 没long long WA了两发,没判-1WA了一发,二分写错WA了一发 最 ...
- bzoj千题计划250:bzoj3670: [Noi2014]动物园
http://www.lydsy.com/JudgeOnline/problem.php?id=3670 法一:KMP+st表 抽离nxt数组,构成一棵树 若nxt[i]=j,则i作为j的子节点 那么 ...
随机推荐
- 【JLOI2015】城池攻占
左偏树加lazy操作即可 # include <stdio.h> # include <stdlib.h> # include <string.h> # inclu ...
- ES6的模块化规范和CommonJS的模块化规范的差异
ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,旨在成为浏览器和服务器通用的模块解决方案.其模块功能主要由两个命令构成:export 和 import.export命令用于规定模块的对 ...
- 部署用于生产的Exceptionlees(一个强大易用的日志收集服务)
Exceptionless是一个非常优秀的事件记录服务,目前我们的自部署的Exceptionless已经稳定运行了近一年的时间,收集了千万条事件信息.但Exceptionless官方自宿主部署的文档不 ...
- C#封装程序集属性方法注释说明
一.使用封装程序集好处: 在很多分布式应用程序开发中,针对每一种功能可能条用的接口不一样,往往习惯将需要被调用的接口,封装成DLL给调用方应用后使用,这样既规范了调用的方式,又避免了调用出现参数请求方 ...
- 去除IE10自带的清除按钮
最近在工作中碰到了一个问题,原本在IE8,IE9下正常的input表单,在IE10下会出现清除按钮,即表单右侧会出现一个可以清除该表单内容的小叉.由于之前一直没有兼容过IE10,所以我专门搜了下原因. ...
- Unity性能优化的N种武器
贴图: l 控制贴图大小,尽量不要超过 1024 x1024: l 尽量使用2的n次幂大小的贴图,否则GfxDriver里会有2份贴图: l 尽量使用压缩格式减小贴图大小: l 若干种贴图合并 ...
- 元素化设计原理及规则v1.0
一.元素设计架构 元素设计架构展示在基于元素化设计的思想下,系统各元素之间如何相互协作,并完成整个系统搭建. 架构中以Entity(数据)为中心,由Entity产生数据库表结构,并且Entity作为业 ...
- 5分钟spark streaming实践之 与kafka联姻
你:kafka是什么? 我:嗯,这个嘛..看官网. Apache Kafka® is a distributed streaming platform Kafka is generally used ...
- PHP编程效率的20个要点--PHP技术教程分享
用单引号代替双引号来包含字符串,这样做会更快一些.因为PHP教程会教你在双引号包围的字符串中搜寻变量,单引号则 不会,注意:只有echo能这么做,它是一种可以把多个字符串当作参数的“函数”(译注:兄弟 ...
- 【重要】ionic和Angular的安装步骤
首先搭建好npm和node环境的最新版本安装:: 一:开始安装ionic: 1. npm install -g ionic(全局安装ionic) 2. ionic start 新建的项目名称 +模板样 ...