看错题目了,想成每个城市都可以买一个东西,然后在后面的某个城市卖掉,问最大收益.这个可以类似维护上升序列的方法在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 线段树区间提取 有序链剖的更多相关文章

  1. 树链剖分——线段树区间合并bzoj染色

    线段树区间合并就挺麻烦了,再套个树链就更加鬼畜,不过除了代码量大就没什么其他的了.. 一些细节:线段树每个结点用结构体保存,pushup等合并函数改成返回一个结构体,这样好写一些 struct Seg ...

  2. hdu 3966(树链剖分+线段树区间更新)

    传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...

  3. 计蒜客 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 ...

  4. 【bzoj2325】[ZJOI2011]道馆之战 树链剖分+线段树区间合并

    题目描述 给定一棵树,每个节点有上下两个格子,每个格子的状态为能走或不能走.m次操作,每次修改一个节点的状态,或询问:把一条路径上的所有格子拼起来形成一个宽度为2的长方形,从起点端两个格子的任意一个开 ...

  5. [NOI2015] 软件包管理器【树链剖分+线段树区间覆盖】

    Online Judge:Luogu-P2146 Label:树链剖分,线段树区间覆盖 题目大意 \(n\)个软件包(编号0~n-1),他们之间的依赖关系用一棵含\(n-1\)条边的树来描述.一共两种 ...

  6. Bzoj 1798: [Ahoi2009]Seq 维护序列seq(线段树区间操作)

    1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MB Description 老师交给小可可一个维护数列的任务,现在小可 ...

  7. POJ 2823 Sliding Window 线段树区间求和问题

    题目链接 线段树区间求和问题,维护一个最大值一个最小值即可,线段树要用C++交才能过. 注意这道题不是求三个数的最大值最小值,是求k个的. 本题数据量较大,不能用N建树,用n建树. 还有一种做法是单调 ...

  8. CF444C. DZY Loves Colors[线段树 区间]

    C. DZY Loves Colors time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  9. HDU 4509 湫湫系列故事——减肥记II(线段树-区间覆盖 或者 暴力技巧)

    http://acm.hdu.edu.cn/showproblem.php?pid=4509 题目大意: 中文意义,应该能懂. 解题思路: 因为题目给的时间是一天24小时,而且还有分钟.为了解题方便, ...

随机推荐

  1. Spark记录-Scala语法基础

    参考:http://docs.scala-lang.org/cheatsheets/index.html.http://docs.scala-lang.org/.http://www.scala-la ...

  2. RESTful记录-RESTful服务

    按照REST架构,一个RESTful Web服务不应该继续服务器的客户端的状态.这种限制被称为无状态.它负责客户以它的上下文传递给服务器,然后服务器可以存储这样的上下文,以处理客户端的进一步请求.例如 ...

  3. ASP.NET MVC学习(五)之MVC原理解析

    ASP.NET MVC 请求生命周期 生命周期步骤概览 当我们对ASP.NET MVC网站发出一个请求的时候,会发生5个主要步骤: 步骤1:创建RouteTable 当ASP.NET应用程序第一次启动 ...

  4. [整理]Error: [ngRepeat:dupes]的解决方法

    sdfsadf <div class="pageNum middle PT10"> <a href="javascript:void(0);" ...

  5. Docker学习笔记二 使用镜像

    本文地址:https://www.cnblogs.com/veinyin/p/10408363.html  Docker运行容器前,需本地存在对应镜像,若没有则Docker从镜像仓库下载该镜像.  镜 ...

  6. 200行代码实现RPC框架

    之前因为项目需要,基于zookeeper和thrift协议实现了一个简单易用的RPC框架,核心代码不超过200行. zookeeper主要作用是服务发现,thrift协议作为通信传输协议, 基于com ...

  7. 图的最短路径-----------Dijkstra算法详解(TjuOj2870_The Kth City)

    做OJ需要用到搜索最短路径的题,于是整理了一下关于图的搜索算法: 图的搜索大致有三种比较常用的算法: 迪杰斯特拉算法(Dijkstra算法) 弗洛伊德算法(Floyd算法) SPFA算法 Dijkst ...

  8. aps.net webform框架下页面服务器端控件和html控件用法

    (1)select 下拉框 前端: <select name="gameserverlist" id="gameserverlist" runat=&qu ...

  9. networkManger介绍

    http://www.linuxidc.com/Linux/2013-08/88809.htm

  10. nc用法【转】

    linux nc命令使用详解 功能说明:功能强大的网络工具 语 法:nc [-hlnruz][-g<网关...>][-G<指向器数目>][-i<延迟秒数>][-o& ...