【LuoguP3038/[USACO11DEC]牧草种植Grass Planting】树链剖分+树状数组【树状数组的区间修改与区间查询】
模拟题,可以用树链剖分+线段树维护。
但是学了一个厉害的。。树状数组的区间修改与区间查询。。
分割线里面的是转载的:
--------------------------------------------------------------------------------
[ 3 ] 上面都不是重点……重点是树状数组的区间修改+区间查询 这个很好玩 其实也挺简单
首先依旧是引入delta数组 delta[i]表示区间 [i, n] 的共同增量 于是修改区间 [l, r] 时修改 delta[l] 和 delta[r + 1] 即可(就是差分的思路)
查询的时候是查询区间 [l, r] 的和 即sum[r] - sum[l - 1] 所以现在的问题是求sum[i]
sum[i] = a[]+...+a[i] + delta[]*i + delta[]*(i - ) + delta[]*(i - )+...+delta[i]* // a[i]为原始数组
= sigma( a[x] ) + sigma( delta[x] * (i + - x) )
= sigma( a[x] ) + (i + ) * sigma( delta[x] ) - sigma( delta[x] * x )
其中 sigma( a[x] ) 是可以预处理出来的 于是只需要维护 delta[x] 与 delta[x] * x 的前缀和(作为两个树状数组就可以了)
为了试验这个方法我专门去找了之前写线段树挂了好久的例题 = = codevs1082 线段树练习3
然后交树状数组的代码是 324ms 内存5M过了 线段树是1027ms 13M 如果去掉读入优化的话代码会更短。
--------------------------------------------------------------------------------------------------------------------------
转自:http://blog.csdn.net/qq_21841245/article/details/43956633
很好。。这题本机测系统暴栈了。。交上去才A。。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<ctime>
#include<queue>
using namespace std; const int N=*,S=,D=;
struct node{
int x,y,next;
}a[*N];
struct trnode{
int l,r,lc,rc,d;
}t[*N];
int n,m,len,num,first[N],dep[N],f[N][S],tot[N],zs[N],dfn[N],top[N],c0[N],c1[N],delta[N];
char s[]; void add(int x,int d)
{
for(int i=x;i<=n;i+=(i&(-i))) c0[i]+=d,c1[i]+=d*x;
} int getsum(int x)
{
int a0=,a1=;
for(int i=x;i>=;i-=(i&(-i))) a0+=c0[i],a1+=c1[i];
return a0*(x+)-a1;
} void ins(int x,int y)
{
a[++len].x=x;a[len].y=y;
a[len].next=first[x];first[x]=len;
} void dfs(int x,int fa)
{
dep[x]=dep[fa]+;
f[x][]=fa;
tot[x]=;
zs[x]=;
for(int i=first[x];i;i=a[i].next)
{
int y=a[i].y;
if(y==fa) continue;
dfs(y,x);
tot[x]+=tot[y];
if(zs[x]== || tot[y]>tot[zs[x]]) zs[x]=y;
}
} void find_top(int x,int fa)
{
dfn[x]=++num;
if(zs[x])
{
top[zs[x]]=top[x];
find_top(zs[x],x);
}
for(int i=first[x];i;i=a[i].next)
{
int y=a[i].y;
if(y==fa || y==zs[x]) continue;
top[y]=y;
find_top(y,x);
}
} int solve(int x,int y,int tmp)
{
int tx=top[x],ty=top[y],ans=;
while(tx!=ty)
{
if(dep[tx]<dep[ty]) swap(x,y),swap(tx,ty);
if(tmp==)
{
add(dfn[tx],);
add(dfn[x]+,-);
}
else ans+=getsum(dfn[x])-getsum(dfn[tx]-);
x=f[top[x]][];tx=top[x];
}
if(x==y) return ans;
else
{
if(dep[x]<dep[y]) swap(x,y);
if(tmp==)
{
add(dfn[y]+,);
add(dfn[x]+,-);
}
else ans+=getsum(dfn[x])-getsum(dfn[y]);
return ans;
}
} void lca_init()
{
for(int j=;j<=D;j++)
for(int i=;i<=n;i++)
f[i][j]=f[f[i][j-]][j-];
} int lca_query(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=D;i>=;i--)
{
if(f[x][i]==) continue;
if(dep[f[x][i]]>=dep[y]) x=f[x][i];
}
if(x==y) return x;
for(int i=D;i>=;i--)
{
if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
}
return f[x][];
} int main()
{
freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
// freopen("grassplant.in","r",stdin);
// freopen("grassplant.out","w",stdout);
scanf("%d%d",&n,&m);
int x,y,z;len=;num=;
memset(first,,sizeof(first));
memset(f,,sizeof(f));
memset(c0,,sizeof(c0));
memset(c1,,sizeof(c1));
memset(dep,,sizeof(dep));
memset(tot,,sizeof(tot));
memset(zs,,sizeof(zs));
memset(dfn,,sizeof(dfn));
for(int i=;i<n;i++)
{
scanf("%d%d",&x,&y);
ins(x,y);
ins(y,x);
}
dfs(,);
top[]=;find_top(,);
// for(int i=1;i<=n;i++)
// {
// printf("i = %d dep = %d zs = %d tot = %d dfn = %d top = %d\n",i,dep[i],zs[i],tot[i],dfn[i],top[i]);
// }
lca_init();
for(int i=;i<=m;i++)
{
scanf("%s",s);
scanf("%d%d",&x,&y);
if(s[]=='P')
{
z=lca_query(x,y);
solve(x,z,);
solve(y,z,);
}
else
{
printf("%d\n",solve(x,y,));
}
}
return ;
}
【LuoguP3038/[USACO11DEC]牧草种植Grass Planting】树链剖分+树状数组【树状数组的区间修改与区间查询】的更多相关文章
- 洛谷P3038 [USACO11DEC]牧草种植Grass Planting
题目描述 Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirectional road ...
- [USACO11DEC]牧草种植Grass Planting
图很丑.明显的树链剖分,需要的操作只有区间修改和区间查询.不过这里是边权,我们怎么把它转成点权呢?对于E(u,v),我们选其深度大的节点,把边权扔给它.因为这是树,所以每个点只有一个父亲,所以每个边权 ...
- 树链剖分【p3038】[USACO11DEC]牧草种植Grass Planting
表示看不太清. 概括题意 树上维护区间修改与区间和查询. 很明显树剖裸题,切掉,细节处错误T了好久 TAT 代码 #include<cstdio> #include<cstdlib& ...
- 洛谷 P3038 [USACO11DEC]牧草种植Grass Planting(树链剖分)
题解:仍然是无脑树剖,要注意一下边权,然而这种没有初始边权的题目其实和点权也没什么区别了 代码如下: #include<cstdio> #include<vector> #in ...
- 洛谷 P3038 [USACO11DEC]牧草种植Grass Planting
题目描述 Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirectional road ...
- P3038 [USACO11DEC]牧草种植Grass Planting
题目描述 Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirectional road ...
- AC日记——[USACO11DEC]牧草种植Grass Planting 洛谷 P3038
题目描述 Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirectional road ...
- HYSBZ 4034 【树链剖分】+【线段树 】
<题目链接> 题目大意: 有一棵点数为 N 的树,以点 1 为根,且树点有权值.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x ...
- BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector
题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...
随机推荐
- 第二十一次ScrumMeeting会议
第二十一次Scrum Meeting 时间:2017/12/11 地点:SPR咖啡馆 人员:王子铭 游心 解小锐 王辰昱 李金奇 杨森 陈鑫 赵晓宇 照片: 目前工作进展 名字 今日 明天的工作 蔡帜 ...
- 冲刺ing-1
冲刺一 1.第一天的工作分配: 姓名 任务分工 吴伟华(队长) 布置团队任务,发表汇总博客及第一次冲刺博客 蔺皓雯 讨论任务分配 杨池宇 讨论任务分配 鲁婧楠 讨论任务分配 曾茜 讨论任务分配 蔡晨旸 ...
- Alpha 冲刺3
队名:日不落战队 安琪(队长) 今天完成的任务 组织第三次站立式会议. 完成了个人信息前端界面. 明天的计划 草稿箱前端界面. 个人信息扩展界面框架. 还剩下的任务 回收站前端界面. 信息修改前端界面 ...
- LintCode-70.二叉树的层次遍历 II
二叉树的层次遍历 II 给出一棵二叉树,返回其节点值从底向上的层次序遍历(按从叶节点所在层到根节点所在的层遍历,然后逐层从左往右遍历) 样例 给出一棵二叉树 {3,9,20,#,#,15,7}, 按照 ...
- iOS- iPad里有趣的UIPopoverController
效果: 1.对UIPopoverController的简单概述 1.1 UIPopoverController是在iPad开发中常用的一个组件(在iPhone上不允许使用),使用非常简单 1.2 ...
- iOS- 网络访问两种常用方式【GET & POST】实现的几个主要步骤
1.前言 上次,在博客里谈谈了[GET & POST]的区别,这次准备主要是分享一下自己对[GET & POST]的理解和实现的主要步骤. 在这就不多废话了,直接进主题,有什么不足的欢 ...
- iOS 出现错误reason: image not found的解决方案
在制作framework时遇到真机运行时导致的reason: image not found允许崩溃的问题,下面是我的解决方案: 首先我们分析一下出现这种情况的原因,原因就是framework找不到镜 ...
- error LNK2019: 无法解析的外部符号 该符号在函数 中被引用 解决方案
需要添加lib或者dll库.项目-属性-配置属性-链接器-输入-附件依赖项,添加需要的lib. 例如我在运行OSG程序的时候,忘记添加了附件依赖项就会报这个错. 解决方案如图.
- Winform 子窗体设置刷新父窗体
方法1:所有权法 父窗体:Form1 子窗体:Form2 //Form1:窗体代码 //需要有一个公共的刷新方法 public void Refresh_Method() { //... } / ...
- 文件传输底层是二进制 所以在传输前可以通过 InputStreamer 指定传输出的编码格式
文件传输底层是二进制 所以在传输前可以通过 InputStreamer 指定传输出的编码格式