Codeforces Round #425 (Div. 2) D 树链剖分 + 树状数组维护区间
一看就知道 可以LCA判断做 也可以树链剖分拿头暴力
然而快速读入和线段树维护区间会T70 于是只能LCA?
线段树的常数不小 于是需要另外一种办法来进行区间加减和查询区间和 就是使用树状数组
这个题的代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
#define pb push_back int n , qn ;
vector<int > q [100050] ;
int top[100050] , fa[100050] , deep[100050] , num[100050] , p[100050] , fp[100050] , son[100050] , pos ; inline int read()
{
int x=0;char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x;
} ///---------- int c[100050] ;
int d[100050] ;
int lowbit(int x) {
return (x & (-x)) ;
}
void add(int c[] , int x ,int val) {
while(x <= n+5) {
c[x] += val ; x += lowbit(x) ;
}
}
int sum(int c[] , int x) {
int res = 0 ;
while(x > 0) {
res += c[x] ;
x -= lowbit(x) ;
}
return res ;
}
void add(int l , int r , int val) {
add(c , l , val) ; add(d , l , l * val) ;
add(c , r+1 , -val ) ; add(d , r + 1 , -val * (r+1)) ;
}
int sum(int x) {
return (x + 1) * sum(c , x) - sum(d , x) ;
}
int sum(int l , int r) {
return sum(r) - sum(l - 1) ;
} ///---------- void dfs1(int u , int pre , int d) {
deep[u] = d ;
fa[u] = pre ;
num[u] = 1 ;
for(int i = 0 ; i < q[u].size() ; i ++ ) {
int v = q[u][i] ;
if(v != pre) {
dfs1(v , u , d+1) ;
num[u] += num[v] ;
if(son[u] == -1 || num[v] > num[son[u]]) {
son[u] = v ;
}
}
}
}
void getpos(int u , int sp) {
top[u] = sp ;
p[u] = pos ++ ;
fp[p[u]] = u ;
if(son[u] == -1) return ;
getpos(son[u] , sp) ;
for(int i = 0 ; i < q[u].size() ; i ++ ) {
int v = q[u][i] ;
if(v != son[u] && v != fa[u]) {
getpos(v , v) ;
}
}
}
void chang(int u , int v , int val) {
int f1 = top[u] , f2 = top[v] ;
int tmp = 0 ;
while(f1 != f2) {
if(deep[f1] < deep[f2]) {
swap(f1 , f2) ; swap(u , v) ;
}
add(p[f1] , p[u] , val) ;
u = fa[f1] ;
f1 = top[u] ;
}
if(deep[u] > deep[v]) swap(u , v) ;
add(p[u] , p[v] , val) ;
}
int que(int u , int v) {
int f1 = top[u] , f2 = top[v] ;
int tmp = 0 ;
while(f1 != f2) {
if(deep[f1] < deep[f2]) {
swap(f1 , f2) ; swap(u , v) ;
}
tmp += sum(p[f1] , p[u]) ;
u = fa[f1] ;
f1 = top[u] ;
}
if(deep[u] > deep[v]) swap(u , v) ;
tmp += sum(p[u] , p[v]) ;
return tmp ;
} int main () {
n = read() ;
qn = read() ;
for(int i = 2 ; i <= n ; i ++ ) {
int z ; z = read() ;
q[z].pb(i) ; q[i].pb(z) ;
}
memset(son , -1 , sizeof(son)) ;
pos = 1 ;
dfs1(1,0,0) ;
getpos(1 , 1) ;
while(qn -- ) {
int aa , bb , cc ;
aa = read() ; bb = read() ; cc = read() ; int ans = 0 ; chang(aa,bb,1) ;
ans = max(que(bb,cc) , ans) ;
chang(aa,bb,-1) ; chang(aa,cc,1) ;
ans = max(que(bb,cc) , ans) ;
chang(aa,cc,-1) ; chang(aa,bb,1) ;
ans = max(que(aa,cc) , ans) ;
chang(aa,bb,-1) ; printf("%d\n" , ans) ;
}
}
其中的树状数组 拿两个数组来分别维护 具体代码
int c[100050] ;
int d[100050] ;
int lowbit(int x) {
return (x & (-x)) ;
}
void add(int c[] , int x ,int val) {
while(x <= n+5) {
c[x] += val ; x += lowbit(x) ;
}
}
int sum(int c[] , int x) {
int res = 0 ;
while(x > 0) {
res += c[x] ;
x -= lowbit(x) ;
}
return res ;
}
void add(int l , int r , int val) {
add(c , l , val) ; add(d , l , l * val) ;
add(c , r+1 , -val ) ; add(d , r + 1 , -val * (r+1)) ;
}
int sum(int x) {
return (x + 1) * sum(c , x) - sum(d , x) ;
}
int sum(int l , int r) {
return sum(r) - sum(l - 1) ;
}
树状数组天下无敌TAT 于是又上网学习了新姿势 我有姿势我自豪
树状数组单点修改 + 区间查询max
int num[5000] ;
int c[5000] ;
int n ;
int lowbit(int x)
{
return x & (-x);
}
void updata(int x)
{
int lx, i;
while (x <= n)
{
c[x] = num[x];
lx = lowbit(x);
for (i=1; i<lx; i<<=1)
c[x] = max(c[x], c[x-i]);
x += lowbit(x);
}
}
int query(int L, int R)
{
int ans = 0;
while (R >= L)
{
ans = max(num[R], ans);
R --;
for (; R-lowbit(R) >= L; R -= lowbit(R))
ans = max(c[R], ans);
}
return ans;
}
以及这里还有...矩形增减 + 矩形查询和的黑科技。。。
http://blog.csdn.net/lawrence_jang/article/details/8054173
Codeforces Round #425 (Div. 2) D 树链剖分 + 树状数组维护区间的更多相关文章
- Codeforces Round #425 (Div. 2) D.Misha, Grisha and Underground
我奇特的脑回路的做法就是 树链剖分 + 树状数组 树状数组是那种 区间修改,区间求和,还有回溯的 当我看到别人写的是lca,直接讨论时,感觉自己的智商收到了碾压... #include<cmat ...
- 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结点最短路径上所有节 ...
- 2018中国大学生程序设计竞赛 - 网络选拔赛 1010 YJJ's Salesman 【离散化+树状数组维护区间最大值】
题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6447 YJJ's Salesman Time Limit: 4000/2000 MS (Java/O ...
- bzoj 2819 Nim dfn序+树状数组维护区间异或值
题目大意 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略 ...
- Codeforces Round #425 (Div. 2) Problem D Misha, Grisha and Underground (Codeforces 832D) - 树链剖分 - 树状数组
Misha and Grisha are funny boys, so they like to use new underground. The underground has n stations ...
- Codeforces Round #329 (Div. 2) D. Happy Tree Party 树链剖分
D. Happy Tree Party Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/593/p ...
- Codeforces Round #425 (Div. 2) - D
题目链接:http://codeforces.com/contest/832/problem/D 题意:给定一棵n个点的树,然后给你q个询问,每个询问为三元组(a,b,c),问你从这三个点中选取一个作 ...
随机推荐
- Javascript中的函数中的this值
看下面这段代码会在控制台上输出什么内容? <script> var url="fang.com"; var obj={ url:"soufun.com&quo ...
- bootstrap获取总条目数
$('#table').on('load-success.bs.table', function () {alert($('#table').bootstrapTable('getOptions'). ...
- proguard-project.txt和project.properties混淆代码
[转]利用android proguard混淆代码 防止反编译,优化代码 网上虽然有很多相关博客,不过貌似都不是最新版的..于是百度+谷歌+github上的开源demo,终于成功的配置了androi ...
- Python 编码(一)— Python3
Unicode 什么是 Unicode 标准 unicode 标准 Unicode 为每个字符提供了一个独特的数字,并且跨平台.设备.应用或者编程语言都是通用的. -- 来自 http://unico ...
- DRDS和RDS主要用来存储用户交易信息,MongoDB主要用来存储商品维度信息
数据集成Data Integration-数加-大数据-阿里云 https://www.aliyun.com/product/cdp 数据集成支持的数据源 数据源类型 数据源 来源数据源被读取 目标数 ...
- 【转】PowerVM 的主要组成部分及概念
PowerVM 是在基于 IBM POWER 处理器的硬件平台上提供的具有行业领先水平的虚拟化技术家族.它是 IBM Power System 虚拟化技术全新和统一的品牌(逻辑分区,微分区,Hyper ...
- random生成六位随机数验证码
需求: 生成一个六位随机验证码 # 傻瓜式纯数字实现import randomran = random.randint(100000, 999999) # ran = random.randrange ...
- 我的Android进阶之旅------>Android中查看应用签名信息
一.查看自己的证书签名信息 如上一篇文章<我的Android进阶之旅------>Android中制作和查看自定义的Debug版本Android签名证书>地址:http://blog ...
- PAT 1074 宇宙无敌加法器 (20 分)
地球人习惯使用十进制数,并且默认一个数字的每一位都是十进制的.而在 PAT 星人开挂的世界里,每个数字的每一位都是不同进制的,这种神奇的数字称为“PAT数”.每个 PAT 星人都必须熟记各位数字的进制 ...
- 002-JVM运行时数据区【内存模型】
一.概述 JVM定义了不同运行时数据区,他们是用来执行应用程序的.某些区域随着JVM启动及销毁,另外一些区域的数据是线程性独立的,随着线程创建和销毁. 1.1.jvm自身物理结构 1.2.java内存 ...