【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
题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...
随机推荐
- LintCode-381.螺旋矩阵 II
螺旋矩阵 II 给你一个数n生成一个包含1-n^2的螺旋形矩阵 样例 n = 3 矩阵为 [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ] 标 ...
- 活学活用wxPython
http://www.czug.org/python/wxpythoninaction/
- 软工网络15团队作业4——Alpha阶段敏捷冲刺-4
一.当天站立式会议照片: 二.项目进展 昨天已完成的工作: 完成程序副界面的设计与信息的输入统计 明天计划完成的工作: 日期等细致信息的处理 工作中遇到的困难: 对微信小程序开发的代码构成有了一些了解 ...
- java 基础--switch--003
1,break可以省略吗? default中的可以省略,其他的如果省略会执行下一个case,从下一个case的 break中中断.(case穿透) 2,default一定要在最后吗? 不是,可以在任意 ...
- EJB介绍
EJB定义: 被称为java企业bean,服务器端组件,核心应用是部署分布式应用程序.用它部署的系统不限定平台.实际上EJB是一种产品,描述了应用组件要解决的标准. 标准: 可扩展 (Scalable ...
- hdu 1851(A Simple Game)(sg博弈)
A Simple Game Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/65535 K (Java/Others)Tot ...
- (七)Redis对键key的操作
key的全部命令如下: keys pattern # 查找所有符合给定模式pattern的key ,查找所有key 使用[keys *] del key1 key2 ... # 删除给定的一个或多个k ...
- HTML、 CSS、 JavaScript三者的关系 1
HTML. CSS. JavaScript三者的关系 网页主要由三部分组成: 结构( Structure) . 表现( Presentation) 和行为( Behavior) HTML —— ...
- [NOIP2016 TG D2T3]愤怒的小鸟
题目大意:有一架弹弓位于(0,0)处,每次可以用它向第一象限发射一只小鸟,飞行轨迹均为形如y=ax2+bxy=ax+bx2 y=ax2+bx的曲线,且必须满足a<0(即是下开口的) 平面的第一象 ...
- 洛谷 P3242 [HNOI2015]接水果 解题报告
P3242 [HNOI2015]接水果 题目描述 风见幽香非常喜欢玩一个叫做 \(osu!\) 的游戏,其中她最喜欢玩的模式就是接水果.由于她已经\(DT\) \(FC\) 了\(\tt{The\ b ...