【 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 ...
随机推荐
- U3D 2D游戏之黑暗纪元 2D游戏基础入门开发全(1)
第一个U3D 2D游戏的例子,全部自己编写,算是入门用,这里记录一下. 1.首先游戏把层次布置好,这里分为 背景层,游戏层,UI层 背景层 (Background-1):就是单纯的背景显示作用. 游戏 ...
- ibatis调存储过程返回游标
http://blog.sina.com.cn/s/blog_6f3ca78f01010pmj.html iBatic调用与JAVA调用很类似,只是JAVA把参数的注册放到了类里面,而iBatis把参 ...
- php session_id()函数介绍及代码实例
session_id()功能: 获取设置当前回话ID. 函数说明: string session_id ([ string $id ] ) 参数: 如果指定了参数$id,那么函数会替换当前的回话id. ...
- C#获取当前路径,获取当前路径的上一层路径
C#获取当前路径的方法如下: (1)string path1 = System.Environment.CurrentDirectory; //C:\...\bin\Debug -获取和设置当前工作目 ...
- jsp 页面获取xml的内容
<c:out value="${history.xml}" escapeXml="true" />
- iOS开发——视频播放 待更新……
本文主要实现调用系统自带的播放器,自带的播放器已经做好了屏幕的适配,集成播放,暂停,快进等功能.能够满足基本的视频播放功能及iOS的视频播放的开发. 最后将其简单的封装成一个iOS视频播放工具类. 一 ...
- Cell的重用机制
static NSString *resuseId=@"cell"; UITableViewCell *cell=[tableView dequeueReusableCellWit ...
- TFTPD32, 3CDaemon, FlashFxp
TFTPD32, 3CDaemon, FlashFxp ——各种网络传输下载工具简介—— 一.将3CDaemon.exe作为TFTP服务端,开发板作为TFTP客户端 1.如上图所示,设置好3CDaem ...
- stack around the variable “XX” was corrupted
晚上花了几个小时fix了这个恼人的BUG!“在变量XX周围的堆栈已损坏” 在网上找到的解释是: 把“project->配置属性->c/c++->代码生成->基本运行时检查 设置 ...
- 基于ACE的定时器模板类
ACETimerClockGenerator.h ClockGeneratorIF.h 在类中定义一个结构体,在结构体中定义一个函数. 在结构体中定义一个函数,这样做有什么好呢? TimerHandl ...