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: 震波的更多相关文章

  1. bzoj千题计划300:bzoj4823: [Cqoi2017]老C的方块

    http://www.lydsy.com/JudgeOnline/problem.php?id=4823 讨厌的形状就是四联通图 且左右各连一个方块 那么破坏所有满足条件的四联通就好了 按上图方式染色 ...

  2. bzoj千题计划196:bzoj4826: [Hnoi2017]影魔

    http://www.lydsy.com/JudgeOnline/problem.php?id=4826 吐槽一下bzoj这道题的排版是真丑... 我还是粘洛谷的题面吧... 提供p1的攻击力:i,j ...

  3. bzoj千题计划280:bzoj4592: [Shoi2015]脑洞治疗仪

    http://www.lydsy.com/JudgeOnline/problem.php?id=4592 注意操作1 先挖再补,就是补的范围可以包含挖的范围 SHOI2015 的题 略水啊(逃) #i ...

  4. bzoj千题计划177:bzoj1858: [Scoi2010]序列操作

    http://www.lydsy.com/JudgeOnline/problem.php?id=1858 2018 自己写的第1题,一遍过 ^_^ 元旦快乐 #include<cstdio> ...

  5. bzoj千题计划317:bzoj4650: [Noi2016]优秀的拆分(后缀数组+差分)

    https://www.lydsy.com/JudgeOnline/problem.php?id=4650 如果能够预处理出 suf[i] 以i结尾的形式为AA的子串个数 pre[i] 以i开头的形式 ...

  6. bzoj千题计划304:bzoj3676: [Apio2014]回文串(回文自动机)

    https://www.lydsy.com/JudgeOnline/problem.php?id=3676 回文自动机模板题 4年前的APIO如今竟沦为模板,,,╮(╯▽╰)╭,唉 #include& ...

  7. bzoj千题计划292:bzoj2244: [SDOI2011]拦截导弹

    http://www.lydsy.com/JudgeOnline/problem.php?id=2244 每枚导弹成功拦截的概率 = 包含它的最长上升子序列个数/最长上升子序列总个数 pre_len ...

  8. bzoj千题计划278:bzoj4590: [Shoi2015]自动刷题机

    http://www.lydsy.com/JudgeOnline/problem.php?id=4590 二分 这么道水题 没long long WA了两发,没判-1WA了一发,二分写错WA了一发 最 ...

  9. bzoj千题计划250:bzoj3670: [Noi2014]动物园

    http://www.lydsy.com/JudgeOnline/problem.php?id=3670 法一:KMP+st表 抽离nxt数组,构成一棵树 若nxt[i]=j,则i作为j的子节点 那么 ...

随机推荐

  1. 【BZOJ4010】【HNOI2015】菜肴制作(拓扑排序)

    [BZOJ4010][HNOI2015]菜肴制作(拓扑排序) 题面 Description 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为 ...

  2. emacs配置

    原配置 (global-set-key [f9] 'compile-file) (global-set-key [f10] 'gud-gdb) (global-set-key (kbd "C ...

  3. [BZOJ1016] [JSOI2008] 最小生成树计数 (Kruskal)

    Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的 ...

  4. [BZOJ1005] [HNOI2008] 明明的烦恼 (prufer编码)

    Description 自从明明学了树的结构,就对奇怪的树产生了兴趣......给出标号为1到N的点,以及某些点最终的度数,允许在任意两点间连线,可产生多少棵度数满足要求的树? Input 第一行为N ...

  5. 常用表单验证&&常用正则

    ### 表单验证&&常用正则 ;(function(ELF){ ELF = ELF || (window.ELF = {}); var reg = {}, pattern = { /* ...

  6. FJUT16级第一周寒假作业题解J题

    题目链接:http://210.34.193.66:8080/vj/Contest.jsp?cid=160#P9 涨姿势之区间刷新 TimeLimit:2000MS  MemoryLimit:128M ...

  7. django Forbidden

    Forbidden (CSRF cookie not set.)解决方法 Forbidden (CSRF cookie not set.):xxx解决方法:在django项目的settings.py文 ...

  8. 简简单单把event loop说清楚

    event loop这东西,确实把我坑了一把,面试的时候被问到这个问题的时候,我是懵逼的,完全不知道怎么回答,而当我回来查到原来这个听起来如此玄乎又厉害的名字就是异步和单线程那块的知识的时候,我心情又 ...

  9. hidden symbol `pthread_atfork'

    gcc交叉编译时发生这种错误 /.. .../voice_demo: hidden symbol `pthread_atfork' in /opt/gcc-linaro-aarch64-linux-g ...

  10. delphi XE Datasnap SERVER 在windows 7 下为服务添加描述信息

    网上对服务添加描述信息的,多数是用注册表的方式,而注册表的方式,我在win7 下测试,不知为什么,总是不行,把执行的CMD以管理员模式开启,还是没加进去. 于是在网上查到下面的代码,保存供叁考,原文博 ...