【 SPOJ - GRASSPLA】 Grass Planting (树链剖分+树状数组)
54 种草
约翰有 N 个牧场,编号为 1 到 N。它们之间有 N − 1 条道路,每条道路连接两个牧场。通过这
些道路,所有牧场都是连通的。
刚开始的时候,所有道路都是光秃秃的,没有青草。约翰会在一些道路上批量种草。每次开始种
草的时候,约翰会选择一个牧场作为起点,一个牧场作为终点,找到从起点到终点的最短路径,在这
条路径上所有的道路上分别种下一棵新的青草。
贝西在监督约翰的工作,她迫不及待地想知道每条道路上已经有多少青草了。约翰的工作总是被
贝西打断,他不胜其烦,所以请你来帮忙回答贝西的问题。约翰的工作和贝西的询问是穿插进行的,
输入数据将会依次出现 M 个事件,以字符 P 开头的事件表示约翰在一条路径上种植了青草,以字符
Q 开头的事件表示贝西在查询一条道路上有多少青草。
输入格式
• 第一行:两个整数 N 和 M, 2 ≤ N ≤ 105 , 1 ≤ M ≤ 105
• 第二行到第 N 行:第 i + 1 行有两个整数 Ui 和 Vi,表示第 i 条道路连接的两个牧场编号,
1 ≤ Ui,Vi ≤ N
• 第 N + 1 行到第 N + Q 行:每行首先由一个大写字母:
– 如果是 P,随后会有两个整数 A 和 B,表示约翰在从 A 通向 B 的每条道路上都新种了一
棵青草, 1 ≤ A,B ≤ N
– 如果是 Q,随后会有两个整数 A 和 B,表示贝西查询一条道路上的青草数量, A 和 B 是
这条道路的两个端点, 1 ≤ A,B ≤ N,保证输入数据中存在一条 A 到 B 的道路
输出格式
• 对每个查询请求,输出该条道路上青草的数量,以换行符分隔
样例输入
4 6
1 4
2 4
3 4
P 2 3
P 1 3
Q 3 4
P 1 4
Q 2 4
Q 1 4
样例输出
212
【分析】
因为是树状数组专题,于是我打了树状数组没有打线段树。
表示人生第一次树状数组的区间修改和区间查询(我太垃圾..
其实比线段树可还是短多了,就是维护两个东西的前缀和,一个是delta[i],一个是delta[i]*i,delta[i]表示i~n的共同增量。
具体看我转的那篇东西:http://www.cnblogs.com/Konjakmoyu/p/5981935.html
然后就是树剖啦ORZ,好多年没打了居然还能打出来ORZ...
代码如下:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
#define Maxn 100010 struct node
{
int x,y,next;
}t[Maxn*];int len;
int first[Maxn]; void ins(int x,int y)
{
t[++len].x=x;t[len].y=y;
t[len].next=first[x];first[x]=len;
} char s[]; int sm[Maxn],son[Maxn],fa[Maxn],dep[Maxn];
void dfs(int x,int f)
{
sm[x]=;son[x]=;fa[x]=f;dep[x]=dep[f]+;
for(int i=first[x];i;i=t[i].next) if(t[i].y!=f)
{
int y=t[i].y;
dfs(y,x);
sm[x]+=sm[y];
if(sm[y]>sm[son[x]]) son[x]=y;
}
} int tp[Maxn],dfn[Maxn],cnt;
void dfs2(int x,int tpp)
{
if(x==) return;
dfn[x]=++cnt;tp[x]=tpp;
dfs2(son[x],tpp);
for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x])
{
int y=t[i].y;
if(y==son[x]) continue;
dfs2(y,y);
}
} int c1[Maxn],c2[Maxn]; void ffind(int x,int y,int c)
{
for(int i=x;i<=cnt;i+=i&(-i))
c1[i]+=c,c2[i]+=c*x;
y++;
for(int i=y;i<=cnt;i+=i&(-i))
c1[i]+=-c,c2[i]+=(-c)*y;
} int get_ans(int x,int y)
{
int ans=;
for(int i=y;i>=;i-=i&(-i))
ans+=(y+)*c1[i]-c2[i];
x--;
for(int i=x;i>=;i-=i&(-i))
ans-=(x+)*c1[i]-c2[i];
return ans;
} void change(int x,int y)
{
int tt;
while(tp[x]!=tp[y])
{
if(dep[tp[x]]>dep[tp[y]])
{
tt=x,x=y,y=tt;
}
ffind(dfn[tp[y]],dfn[y],);
y=fa[tp[y]];
}
if(x==y) return;
if(dep[x]>dep[y]) tt=x,x=y,y=tt;
ffind(dfn[x]+,dfn[y],);
} int query(int x,int y)
{
int ans=;
int tt;
while(tp[x]!=tp[y])
{
if(dep[tp[x]]>dep[tp[y]])
{
tt=x,x=y,y=tt;
}
ans+=get_ans(dfn[tp[y]],dfn[y]);
y=fa[tp[y]];
}
if(x==y) return ans;
if(dep[x]>dep[y]) tt=x,x=y,y=tt;
ans+=get_ans(dfn[x]+,dfn[y]);
return ans;
} int main()
{
int n,m;
scanf("%d%d",&n,&m);
len=;
memset(first,,sizeof(first));
for(int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
ins(x,y);ins(y,x);
}
sm[]=;dep[]=;
dfs(,);
cnt=;
dfs2(,); memset(c1,,sizeof(c1));
memset(c2,,sizeof(c2));
for(int i=;i<=m;i++)
{
int x,y;
scanf("%s%d%d",s,&x,&y);
if(s[]=='P')
{
change(x,y);
}
else
{
printf("%d\n",query(x,y));
}
}
return ;
}
【SPOJ GRASSPLA】
2016-10-28 09:56:44
【 SPOJ - GRASSPLA】 Grass Planting (树链剖分+树状数组)的更多相关文章
- hdu 3966 Aragorn's Story(树链剖分+树状数组/线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: 给出一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路 ...
- Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组
Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...
- 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释
P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...
- 【LuoguP3038/[USACO11DEC]牧草种植Grass Planting】树链剖分+树状数组【树状数组的区间修改与区间查询】
模拟题,可以用树链剖分+线段树维护. 但是学了一个厉害的..树状数组的区间修改与区间查询.. 分割线里面的是转载的: ----------------------------------------- ...
- HDU 3966 Aragorn's Story 树链剖分+树状数组 或 树链剖分+线段树
HDU 3966 Aragorn's Story 先把树剖成链,然后用树状数组维护: 讲真,研究了好久,还是没明白 树状数组这样实现"区间更新+单点查询"的原理... 神奇... ...
- bzoj1146整体二分+树链剖分+树状数组
其实也没啥好说的 用树状数组可以O(logn)的查询 套一层整体二分就可以做到O(nlngn) 最后用树链剖分让序列上树 #include<cstdio> #include<cstr ...
- HDU 5044 (树链剖分+树状数组+点/边改查)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5044 题目大意:修改链上点,修改链上的边.查询所有点,查询所有边. 解题思路: 2014上海网赛的变 ...
- BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )
树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. ...
- hdu 3966 Aragorn's Story(树链剖分+树状数组)
pid=3966" target="_blank" style="">题目链接:hdu 3966 Aragorn's Story 题目大意:给定 ...
- (简单) POJ 3321 Apple Tree,树链剖分+树状数组。
Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow ...
随机推荐
- 使用modelsim仿真DDR3时编译出错的解决方法
Modelsim 10.1c release note sates as : Product Changes in 10.1c Release 10.1b introduced a new error ...
- mysql分表,分区的区别和联系
一,什么是mysql分表,分区 什么是分表,从表面意思上看呢,就是把一张表分成N多个小表,具体请看mysql分表的3种方法 什么是分区,分区呢就是把一张表的数据分成N多个区块,这些区块可以在同一个磁盘 ...
- MyEclipse 多项目对应配置多个Tomcat
在MyEclipse的安装目录下,有D:\Program Files\MyEclipse 6.5\myeclipse\eclipse\plugins 的插件路径. 里边很多插件的配置文件包. 找到 ...
- 01_JavaMail_02_Base64加密
[简述] Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一.Base64编码可用于在HTTP环境下传递较长的标识信息.例如,在Java Persistence系统Hibernate中 ...
- 【转】PHP网站常见安全漏洞,及相应防范措施总结
---恢复内容开始--- 目前,基于PHP的网站开发已经成为目前网站开发的主流,本文笔者重点从PHP网站攻击与安全防范方面进行探究,旨在减少网站漏洞,希望对大家有所帮助! 一.常见PHP网站安全漏洞 ...
- spring setter方法注入
<bean id="dao" class="Dao"></bean> <bean id="service" c ...
- 转(sphinx 多索引使用 方法 )
1 http://blog.csdn.net/adparking/article/details/7080278 文章不错 总结 1.索引合并问题,前面已经解释过,两个索引合并时,都要读入,然后还要 ...
- c# 实现文件批量压缩
今天改一个网站的功能,网站提供一些微信的素材,每个页面对应一套素材,如果会员一张一张下载,那么网站交互性就有点太差了.所以修改的内容就是提供一个按钮,点击按钮将这套图片和网站信息进行打包下载. 思路: ...
- c++与C# winform的消息通讯--(结构体与byte数组的使用)
近期正在做一个蓝牙驱动的使用程序,其中有一块从c++发送数据到C#的部分,网上查了很多资料,大多都是介绍如何通过调用函数获取用户数据.并且在消息发送中,很少介绍如何发送一个结构体,并且结构体里面有 b ...
- event的属性
t获取鼠标相对于浏览器左上角的坐标 <div id="dv" style=" width:300px; height:200px; background-color ...