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 (树链剖分+树状数组)的更多相关文章

  1. hdu 3966 Aragorn's Story(树链剖分+树状数组/线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: 给出一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路 ...

  2. Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组

    Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...

  3. 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释

    P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...

  4. 【LuoguP3038/[USACO11DEC]牧草种植Grass Planting】树链剖分+树状数组【树状数组的区间修改与区间查询】

    模拟题,可以用树链剖分+线段树维护. 但是学了一个厉害的..树状数组的区间修改与区间查询.. 分割线里面的是转载的: ----------------------------------------- ...

  5. HDU 3966 Aragorn's Story 树链剖分+树状数组 或 树链剖分+线段树

    HDU 3966 Aragorn's Story 先把树剖成链,然后用树状数组维护: 讲真,研究了好久,还是没明白 树状数组这样实现"区间更新+单点查询"的原理... 神奇... ...

  6. bzoj1146整体二分+树链剖分+树状数组

    其实也没啥好说的 用树状数组可以O(logn)的查询 套一层整体二分就可以做到O(nlngn) 最后用树链剖分让序列上树 #include<cstdio> #include<cstr ...

  7. HDU 5044 (树链剖分+树状数组+点/边改查)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5044 题目大意:修改链上点,修改链上的边.查询所有点,查询所有边. 解题思路: 2014上海网赛的变 ...

  8. BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )

    树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. ...

  9. hdu 3966 Aragorn&#39;s Story(树链剖分+树状数组)

    pid=3966" target="_blank" style="">题目链接:hdu 3966 Aragorn's Story 题目大意:给定 ...

  10. (简单) POJ 3321 Apple Tree,树链剖分+树状数组。

    Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow ...

随机推荐

  1. hibernate----hibernate的基础设置

    本次学习的内容是hibernate的基础设置 具体内容为: 一.准备工作 1.新建java工程 2.自动引入相关库(自动生成SessionFactory) 3.将数据库驱动拿进来 4.添加hibern ...

  2. Linux学习新篇——常用命令和快捷键总结

    最近刚接触Linux,整理了一些常用的命令和快捷键 Tab补全命令 当命令记不清了,输入记得的前几个用Tab就可以将该命令自动补全. 启动tomcat服务用$startup.sh 停止tomcat服务 ...

  3. 监听列表ListVIew的滑动状态

    /*监听列表的滑动状态:暂时用不到 * SCROLL_STATE_FLING 时让图片不显示,提高滚动性能让滚动小姑更平滑 * SCROLL_STATE_IDLE 时显示当前屏幕可见的图片*/ mLi ...

  4. 纯js写图片轮播插件

    最近终于写成了自己创作的图片轮播插件,使用原生js编写.与目前网上流行的轮播插件相比,功能和效果稍弱,但是使用起来相当方便. 先看html代码 <!DOCTYPE html> <ht ...

  5. sublime中使用markdown

    #为知笔记##为知笔记###为知笔记 1. 列表12. 列表23. 列表35. 顺序错了不用担心3. 写错的列表,会自动纠正 为知笔记---------------------- ```cpp int ...

  6. postgresql行转列并拼接字符串

    有这样一张表: ; id |   kw   ----+--------  1 | big  1 | hello  2 | oracle  2 | small  2 | apple  3 | shit( ...

  7. C# 操作数据库的几种方式(数据库使用SQL SERVER2008)

    一:通过常规 T-SQL 语句 (只写删除操作,其他同理) string strConn = ConfigurationManager.ConnectionStrings["SiteConn ...

  8. 那天有个小孩跟我说LINQ(四)转载

    1  LINQ TO SQL(代码下载)       我们以一个酒店管理系统的数据库为例子         表结构很简单:GuestInfo(客人信息表),Room(房间表),RoomType(房间类 ...

  9. mediawiki数据库的下载地址及导入方法

    mediawiki导入数据库 数据库下载:http://zh.wikipedia.org/wiki/Wikipedia:%E6%95%B0%E6%8D%AE%E5%BA%93%E4%B8%8B%E8% ...

  10. ios专题 - 图片(UIImage)获取方法

    说到图片获取的方法,就得看API文档. UIImage生成实例的方法有: 1)imageNamed 从指定文件返回对象. 这个方法有个比较特殊的地方:该方法首先从系统缓存中寻找该图片,如果有,则从缓存 ...