[kuangbin]树链剖分A - Aragorn's Story
比较水的题了,比模板题还要简单一点
理解了这个结构,自己打出来的,但是小错误还是很多,越来越熟练吧希望
错误函数updata,updata_lca,query||错误地方区间往下递归的时候是left <= mid || right > mid
//https://vjudge.net/contest/251031#problem
#include <iostream>
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <cmath>
#define lson rt<<1,left,mid
#define rson rt<<1|1,mid+1,right
#define ls rt<<1
#define rs rt<<1|1
//#define mid ((left + right) >> 1)
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 1e3;
int n,m,p;
int V[maxn];
//邻接表
struct node{
int to,pre;
}e[maxn << 1];
int id[maxn],cnt;
//线段树
int val[maxn << 2],lazy[maxn<<2];
//dfs1
int siz[maxn],dep[maxn],fa[maxn],son[maxn];
//dfs2
int top[maxn],num_id[maxn],id_num[maxn];
int tot;
void init()
{
memset(id,-1,sizeof(id));
memset(son,0,sizeof(son));
cnt = tot = 0;
}
void add(int from,int to)
{
e[cnt].to = to;
e[cnt].pre = id[from];
id[from] = cnt++;
}
void dfs1(int now,int f,int depth)
{
siz[now] = 1;
fa[now] = f;
dep[now] = depth; for(int i = id[now];~i;i = e[i].pre)
{
int to = e[i].to;
if(to != f)
{
dfs1(to,now,depth+1);
siz[now] += siz[to];
if(siz[to] > siz[son[now]])
son[now] = to;
}
}
}
void dfs2(int now,int rt)
{
top[now] = rt;
num_id[now] = ++tot;
id_num[tot] = now; if(!son[now]) return; dfs2(son[now],rt); for(int i = id[now];~i;i = e[i].pre)
{
int to = e[i].to;
if(to != son[now] && to != fa[now])
{
dfs2(to,to);
}
}
}
void pup(int rt)
{
val[rt] = val[ls] + val[rs];
}
void build(int rt,int left,int right)
{
lazy[rt] = 0; if(left == right)
{
val[rt] = V[id_num[left]];
return;
}
int mid = (left + right) >> 1;
build(lson);build(rson);
pup(rt);
}
void pdown(int rt,int left,int right)
{
if(lazy[rt])
{
int lt = lazy[rt];
int mid = (left + right) >> 1;
val[ls] += (mid - left + 1) * lt;
val[rs] += (right - mid) * lt;
lazy[rs] += lt;
lazy[ls] += lt;
lazy[rt] = 0;
}
}
void updata(int rt,int left,int right,int l,int r,int k)
{
if(left > r || right < l)return;
if(l <= left && right <= r)
{
val[rt] += (right - left + 1) * k;
lazy[rt] += k;
return;
}
pdown(rt,left,right); int mid = (left + right) >> 1; if(left <= mid)
updata(lson,l,r,k);
if(right > mid)
updata(rson,l,r,k);
}
void updata_lca(int x,int y,int k)
{
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]])swap(x,y);
updata(1,1,tot,num_id[top[x]],num_id[x],k);
x = fa[top[x]];
}
if(dep[x] < dep[y])swap(x,y);
updata(1,1,tot,num_id[y],num_id[x],k);
}
int query(int rt,int left,int right,int l,int r)
{
int res = 0;
if(left > r || right < l)return 0; if(l <= left && right <= r)
{
return val[rt];
} pdown(rt,left,right); int mid = (left + right) >> 1;
if(left <= mid)res += query(lson,l,r);
if(right > mid)res += query(rson,l,r); return res;
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&p))
{
init();
for(int i = 1;i <= n;++i)
{
scanf("%d",&V[i]);
}
int from,to;
for(int i = 1;i <= m;++i)
{
scanf("%d%d",&from,&to);
add(from,to);
add(to,from);
}
dfs1(1,1,1);
//忘记init
dfs2(1,1);
build(1,1,tot);
//cout<<val[1]<<" "<<val[2]<<" "<<val[3]<<" "<<val[4]<<" "<<val[5]<<endl;正确建树
char op[2];
int x,y,z;
for(int i = 0;i < p;++i)
{
scanf("%s",op);
if(op[0] == 'I')
{
scanf("%d%d%d",&x,&y,&z);
updata_lca(x,y,z);
}
else if(op[0] == 'D')
{
scanf("%d%d%d",&x,&y,&z);
//cout<<num_id[x]<<" "<<num_id[y]<<endl;
updata_lca(x,y,-z);
}
else
{
scanf("%d",&x);
//cout<<num_id[x]<<endl;对
printf("%d\n",query(1,1,tot,num_id[x],num_id[x]));
}
}
}
return 0;
}
/*
3 2 500
1 2 3
2 1
2 3
*/
[kuangbin]树链剖分A - Aragorn's Story的更多相关文章
- [kuangbin]树链剖分 C - Tree
和平常的树链剖分维护边权不同的地方在于对线段树的要求较高 NEGATE 反转区间,也就是a - b 内所有的边权取相反数 而Query询问是最大值,所以也就是维护可取反区间的最大值问题 需要维护的值是 ...
- [kuangbin]树链剖分 D - 染色
https://vjudge.net/contest/251031#problem/Dhttps://blog.csdn.net/kirito_acmer/article/details/512019 ...
- HDU 3966 Aragorn's Story (树链剖分+树状数组)
Aragorn's Story Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- HDU 3966 Aragorn's Story 树链剖分+树状数组 或 树链剖分+线段树
HDU 3966 Aragorn's Story 先把树剖成链,然后用树状数组维护: 讲真,研究了好久,还是没明白 树状数组这样实现"区间更新+单点查询"的原理... 神奇... ...
- hdu 3966 Aragorn's Story(树链剖分+树状数组)
pid=3966" target="_blank" style="">题目链接:hdu 3966 Aragorn's Story 题目大意:给定 ...
- HDU - 3966 Aragorn's Story(树链剖分入门+线段树)
HDU - 3966 Aragorn's Story Time Limit: 3000MS Memory Limit: 32768KB 64bit IO Format: %I64d & ...
- HDU 3966 Aragorn's Story 动态树 树链剖分
Aragorn's Story Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组
Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...
- HDU 3966 Aragorn's Story(树链剖分)(线段树区间修改)
Aragorn's Story Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
随机推荐
- (转)HTTP 错误 404.2 - Not Found 由于 Web 服务器上的“ISAPI 和 CGI 限制”列表设置,无法提供您请求的页面
详细错误:HTTP 错误 404.2 - Not Found. 由于 Web 服务器上的“ISAPI 和 CGI 限制”列表设置,无法提供您请求的页面. 出现环境:win7 + IIS7.0 解决办法 ...
- Kali Linux 网络扫描秘籍
第三章 端口扫描(二) 作者:Justin Hutchens 译者:飞龙 协议:CC BY-NC-SA 4.0 3.6 Scapy 隐秘扫描 执行 TCP 端口扫描的一种方式就是执行一部分.目标端口上 ...
- 探索未知种族之osg类生物---呼吸分解之事件循环一
事件循环和更新循环 终于到了我们嘴里经常念叨的事件循环.更新循环以及渲染循环了.首先我们来区分一下事件循环和渲染循环,他们两个首先是两个不同顺序执行的过程,我们有时候会用到任意node的updateC ...
- BZOJ1059或洛谷1129 [ZJOI2007]矩阵游戏
BZOJ原题链接 洛谷原题链接 通过手算几组例子后,很容易发现,同一列的\(1\)永远在这一列,且这些\(1\)有且仅有一个能产生贡献,行同理. 所以我们可以只考虑交换列,使得每一行都能匹配一个\(1 ...
- UVA 11324.The Largest Clique tarjan缩点+拓扑dp
题目链接:https://vjudge.net/problem/UVA-11324 题意:求一个有向图中结点数最大的结点集,使得该结点集中任意两个结点u和v满足:要目u可以到达v,要么v可以到达u(相 ...
- 英国BBC出的这套中国风海报,设计美哭了!
“中国风”在国际上已经不是“小众”了 之前分享过好莱坞电影的中国风海报 没想到国外的电视剧也看上了中国市场 没错就是英国BBC的最长寿科幻剧—— <神秘博士Doctor Who> 前段时间 ...
- python 字符串占位符的使用
name2='我是{} 我的专业是 {}'.format('张三','计算机科学技术')print(name2)
- office 2007,SQL Server 2008,VS2010安装步骤
office 2007,SQL Server 2008,VS2010的安装顺序是不是office 2007,SQL Server 2008,VS2010呢? 前几天先安装了SQL Server 200 ...
- db2用户权限
前言: DB2数据库权限分为实例级权限(SYSADM.SYSCTRL.SYSMAINT.SYSMON)和DB2数据库级权限(DBAMD.LOAD).DB2中用户所拥有的权限主要考虑三个方面:实 ...
- /bin/sh^M:bad interpreter:
/bin/sh^M:bad interpreter: No such file or directory 这个错误发生在你在windows下编写文件上传到linux服务器去运行的时候. 错误原因:wi ...