bzoj 3999 线段树区间提取 有序链剖
看错题目了,想成每个城市都可以买一个东西,然后在后面的某个城市卖掉,问最大收益.这个可以类似维护上升序列的方法在O(nlog^3n)的时间复杂度内搞定
这道题用到的一些方法:
1. 可以将有关的线段提取出来,然后一起处理.
2. 线段树可以维护两个方向的信息,这样就可以处理树上有序的东西.
/**************************************************************
Problem: 3999
User: idy002
Language: C++
Result: Accepted
Time:3204 ms
Memory:12144 kb
****************************************************************/ #include <cstdio>
#include <cstring>
#include <algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
#define N 50010
using namespace std; typedef long long dnt;
struct Node {
dnt t, b, a[], tag;
int lf, rg;
Node *ls, *rs;
void pushdown() {
if( tag ) {
ls->t += tag;
ls->b += tag;
ls->tag += tag;
rs->t += tag;
rs->b += tag;
rs->tag += tag;
tag = ;
}
}
void update() {
t = max( ls->t, rs->t );
b = min( ls->b, rs->b );
a[] = max( ls->a[], rs->a[] );
a[] = max( a[], rs->t-ls->b );
a[] = max( ls->a[], rs->a[] );
a[] = max( a[], ls->t-rs->b );
}
void modify( int L, int R, int d ) {
if( L<=lf && rg<=R ) {
t += d;
b += d;
tag += d;
return;
}
pushdown();
int mid=(lf+rg)>>;
if( L<=mid ) ls->modify( L, R, d );
if( R>mid ) rs->modify( L, R, d );
update();
}
}pool[N*], *tail=pool, *root; int n, m;
int head[N], dest[N<<], next[N<<], etot;
int aa[N], bb[N];
int fat[N], dep[N], siz[N], son[N], top[N], vid[N];
int qu[N], bg, ed;
Node *su[N], *sv[N];
int tu, tv; void adde( int u, int v ) {
etot++;
dest[etot] = v;
next[etot] = head[u];
head[u] = etot;
}
Node *build( int lf, int rg ) {
Node *nd = ++tail;
if( lf==rg ) {
nd->b = nd->t = bb[lf];
nd->a[] = nd->a[] = ;
nd->lf=lf, nd->rg=rg;
} else {
int mid=(lf+rg)>>;
nd->ls = build( lf, mid );
nd->rs = build( mid+, rg );
nd->lf=lf, nd->rg=rg;
nd->update();
}
return nd;
}
void fetch( Node *nd, int L, int R, Node *(&stk)[N], int &top ) {
int lf=nd->lf, rg=nd->rg;
if( L<=lf && rg<=R ) {
stk[++top] = nd;
return;
}
int mid=(lf+rg)>>;
nd->pushdown();
if( R>mid ) fetch(nd->rs,L,R,stk,top);
if( L<=mid ) fetch(nd->ls,L,R,stk,top);
}
void build_dcp( int s ) {
// fat dep
fat[s] = ;
dep[s] = ;
qu[bg=ed=] = s;
while( bg<=ed ) {
int u=qu[bg++];
for( int t=head[u]; t; t=next[t] ) {
int v=dest[t];
if( v==fat[u] ) continue;
fat[v] = u;
dep[v] = dep[u] + ;
qu[++ed] = v;
}
}
// siz son
for( int i=ed; i>=; i-- ) {
int u=qu[i], p=fat[u];
siz[u]++;
if( p ) {
siz[p] += siz[u];
if( siz[u]>siz[son[p]] ) son[p]=u;
}
}
// top vid
top[s] = s;
vid[s] = ;
for( int i=; i<=ed; i++ ) {
int u=qu[i];
int cur=vid[u]+;
if( son[u] ) {
top[son[u]] = top[u];
vid[son[u]] = cur;
cur += siz[son[u]];
}
for( int t=head[u]; t; t=next[t] ) {
int v=dest[t];
if( v==fat[u] || v==son[u] ) continue;
top[v] = v;
vid[v] = cur;
cur += siz[v];
}
}
// segment
for( int i=; i<=n; i++ )
bb[vid[i]] = aa[i];
root = build( , n );
}
int lca( int u, int v ) {
while( top[u]!=top[v] ) {
if( dep[top[u]]<dep[top[v]] ) swap(u,v);
u = fat[top[u]];
}
return dep[u]<dep[v] ? u : v;
}
dnt query( int u, int v ) {
if( u==v ) return ;
int ca = lca(u,v);
tu = tv = ;
while( top[u]!=top[ca] ) {
fetch(root,vid[top[u]],vid[u],su,tu);
u=fat[top[u]];
}
while( top[v]!=top[ca] ) {
fetch(root,vid[top[v]],vid[v],sv,tv);
v=fat[top[v]];
}
if( u!=ca )
fetch(root,vid[ca],vid[u],su,tu);
else
fetch(root,vid[ca],vid[v],sv,tv);
dnt curt = ;
dnt rt = ;
for( int i=; i<=tv; i++ ) {
rt = max( rt, sv[i]->a[] );
rt = max( rt, curt-sv[i]->b );
curt = max( curt, sv[i]->t );
}
for( int i=tu; i>=; i-- ) {
rt = max( rt, su[i]->a[] );
rt = max( rt, curt-su[i]->b );
curt = max( curt, su[i]->t );
}
return rt;
}
void modify( int u, int v, int d ) {
while( top[u]!=top[v] ) {
if( dep[top[u]]<dep[top[v]] ) swap(u,v);
root->modify(vid[top[u]],vid[u],d);
u=fat[top[u]];
}
if( dep[u]<dep[v] ) swap(u,v);
root->modify(vid[v],vid[u],d);
}
int main() {
scanf( "%d", &n );
for( int i=; i<=n; i++ )
scanf( "%d", aa+i );
for( int i=,u,v; i<n; i++ ) {
scanf( "%d%d", &u, &v );
adde( u, v );
adde( v, u );
}
build_dcp();
scanf( "%d", &m );
for( int t=,u,v,d; t<=m; t++ ) {
scanf( "%d%d%d", &u, &v, &d );
printf( "%lld\n", query(u,v) );
modify(u,v,d);
}
}
bzoj 3999 线段树区间提取 有序链剖的更多相关文章
- 树链剖分——线段树区间合并bzoj染色
线段树区间合并就挺麻烦了,再套个树链就更加鬼畜,不过除了代码量大就没什么其他的了.. 一些细节:线段树每个结点用结构体保存,pushup等合并函数改成返回一个结构体,这样好写一些 struct Seg ...
- hdu 3966(树链剖分+线段树区间更新)
传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...
- 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)
Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...
- 【bzoj2325】[ZJOI2011]道馆之战 树链剖分+线段树区间合并
题目描述 给定一棵树,每个节点有上下两个格子,每个格子的状态为能走或不能走.m次操作,每次修改一个节点的状态,或询问:把一条路径上的所有格子拼起来形成一个宽度为2的长方形,从起点端两个格子的任意一个开 ...
- [NOI2015] 软件包管理器【树链剖分+线段树区间覆盖】
Online Judge:Luogu-P2146 Label:树链剖分,线段树区间覆盖 题目大意 \(n\)个软件包(编号0~n-1),他们之间的依赖关系用一棵含\(n-1\)条边的树来描述.一共两种 ...
- Bzoj 1798: [Ahoi2009]Seq 维护序列seq(线段树区间操作)
1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MB Description 老师交给小可可一个维护数列的任务,现在小可 ...
- POJ 2823 Sliding Window 线段树区间求和问题
题目链接 线段树区间求和问题,维护一个最大值一个最小值即可,线段树要用C++交才能过. 注意这道题不是求三个数的最大值最小值,是求k个的. 本题数据量较大,不能用N建树,用n建树. 还有一种做法是单调 ...
- CF444C. DZY Loves Colors[线段树 区间]
C. DZY Loves Colors time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- HDU 4509 湫湫系列故事——减肥记II(线段树-区间覆盖 或者 暴力技巧)
http://acm.hdu.edu.cn/showproblem.php?pid=4509 题目大意: 中文意义,应该能懂. 解题思路: 因为题目给的时间是一天24小时,而且还有分钟.为了解题方便, ...
随机推荐
- JAVA记录-JSP内容
JSP(JavaServer Pages )是什么? JavaServer Pages(JSP)是一种支持动态内容开发的网页技术它可以帮助开发人员通过利用特殊的JSP标签,其中大部分以<%开始并 ...
- python 基础部分重点复习整理--从意识那天开始进阶--已结
pythonic 风格编码 入门python好博客 进阶大纲 有趣的灵魂 老齐的教程 老齐还整理了很多精华 听说 fluent python + pro python 这两本书还不错! 元组三种遍历, ...
- 一个简单的二叉搜索树(C++实现)
参考:http://www.cnblogs.com/skywang12345/p/3576373.html 这里主要就是自己实现的代码,删除动作有点不一样: #ifndef __BSTREE_H__ ...
- html5 canvas裁剪区域
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- es6笔记(6) Iterator 和 for...of循环
概要 js中的数组.对象,加上ES6中增加的Map.Set四种数据集合. Iterator提供了一种机制,为各种不同的数据结构提供统一的访问机制.任何数据结构只要部署Iterator接口,就可以完成遍 ...
- [转]避免头文件重复包含以及#ifndef 与 #program once 的区别
为了避免同一个文件被include多次,C/C++中有两种方式,一种是#ifndef方式,一种是#pragma once方式.在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两者仍然还是有一 ...
- git使用常用命令
第一部分:个人整理部分(读<Git教程By廖雪峰.pdf>笔记) /* 配置全局参数 */git config --global user.name "username" ...
- http跨域时的options请求
1.背景 在前后端分离的项目中经常会遇到跨域请求的问题,如果没有进行跨域配置,会浏览器请求失败.我一般采用两种解决方案: 1.采用nginx进行转发,是前后端服务处于同一个域下面,从根本上避免跨域问题 ...
- nginx开启gzip压缩前端css,js
利用nginx实现前后端分离, nginx配置文件,nginx.conf配置采用gzip压缩: 在server中添加: gzip on; #开启gzip gzip_min_length 1k; #低于 ...
- Win7下如何使用GCC编译器
很多Linux的爱好者都很熟悉GCC编译器,但是对面初学者,如何去学习GCC使用GCC ,很多人都是直接在电脑上装一个虚拟机,这样不仅安装麻烦,而且占用了很多电脑资源,今天我来教大家如何在Win7使用 ...