【 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 ...
随机推荐
- Mysql 数据库 操作语句
mysql 格式语句规范 如何登陆你的数据库? 举例! 如果你的是 编译安装的花 那就得去编译安装后的那个目录中去,我的是安装到/usr/local/mysql 下登陆数据库:cd /usr/loca ...
- 将table内容输出为csv文件
1.创建 directory create or replace directory tt as'c:\'; SELECT * FROM DBA_OBJECTS DO WHERE DO.OBJECT_ ...
- magento 产品列表排序、分页功能
我们以 catalog_category_layered 控制器为例说明 在catalog.xml 找到catalog_category_layered配置段 <catalog_category ...
- T-SQL通过触发器创建级联更新·级联删除
create trigger t_table_a on table_a for update,dalete begin if exists(select 1 from inserted) update ...
- 快速预览:C# 3.0的新东西
Lambda 表达式: Func<string, string> doubleAppend= x => x + x; Console.WriteLine (doubleAppend( ...
- MVC Filter自定义验证(拦截)
namespace QS.Web.Extensions { /// <summary> /// 验证session.权限 状态 /// </summary> [Attribut ...
- SQL Server调优系列基础篇 - 性能调优介绍
前言 关于SQL Server调优系列是一个庞大的内容体系,非一言两语能够分析清楚,本篇先就在SQL 调优中所最常用的查询计划进行解析,力图做好基础的掌握,夯实基本功!而后再谈谈整体的语句调优. 通过 ...
- 学习笔记_Java_day14—编码实战___一个注册页面的完整流程
- mysql分区功能详细介绍,以及实例
一,什么是数据库分区 前段时间写过一篇关于mysql分表的 的文章,下面来说一下什么是数据库分区,以mysql为例.mysql数据库中的数据是以文件的形势存在磁盘上的,默认放在/mysql/data下 ...
- iOS谋职之OC面试题
iOS谋职之OC面试题 iOS求职之OC面试题 IOS求职之OC面试题 1.Objective-C的类可以多重继承么?可以采用多个协议么? 答:不可以多重继承,可以采用多个协议. 2.#import和 ...