ZOJ 3724 Delivery 树状数组好题
虽然看起来是求最短路,但因为条件的限制,可以转化为区间求最小值。
对于一条small path [a, b],假设它的长度是len,它对区间[a, b]的影响就是:len-( sum[b]-sum[a-1] );(使区间[a,b]的原有长度变长或者变短,变长没有意义,所以我们只考虑变短的情况),因为只能选择一条small path,所以对于每个查询[u, v],就是要选择在区间[u, v]内,让原有长度减少最多的那条small path,即求区间最小值。
离线处理:
将查询和small path放在一起排序,按u从大到小,v从小到大排。
因为我们要从后往前扫,对于每个查询[u, v],我们应当保证在本查询之前的所有[u', v']已经更新进去。
当u < v时,u < u', v' < v,树状数组minv[i]中记录的是以i为区间右端点的所有small path中len-( sum[b]-sum[a-1] )的最小值,答案为[u, v]的区间和+该最小值。
当u > v时,v' < v, u < u',树状数组minv[i]中记录的是从i点走回i点(走了一个圈)的最小值。答案为最小值减去[u, v]的区间和。
------------------------以下吐槽--------------------------
本来以为不是很难的一道树状数组,结果折腾了一晚上……主要是对查询中u>v的情况处理总是各种出问题,之前我是想把1-N扩大一倍变成1-2N,这样对于查询中u>v的情况就可以转换成查询[ u, N+v ]。事实证明这样转换是不对的……画画图看看就知道为啥了。
然后我又想关于N轴对称把点翻转过去,还是1-2N,只不过把查询变成了[ u, 2N - v ]。还是各种出错orz……
最后实在没办法,老老实实的分开处理了……
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm> #define LL long long int using namespace std; const int MAXN = << ;
const int INF = ;
long long int one = ; LL sum[MAXN]; //区间和
LL minv[MAXN];
LL ans[]; int N, M; struct node
{
int l, r;
LL val;
int id;
}; node D[ MAXN << ]; int lowbit( int x )
{
return x & ( -x );
} void Add( int x, LL val )
{
while ( x <= N )
{
minv[x] = min( minv[x], val );
x += lowbit(x);
}
return;
} LL Query( int x )
{
LL res = one << ;
while ( x > )
{
res = min( res, minv[x] );
x -= lowbit(x);
}
return res;
} bool cmp( node a, node b )
{
if ( a.l != b.l ) return a.l > b.l;
if ( a.r != b.r ) return a.r < b.r;
return a.id < b.id;
} int main()
{
//freopen( "in.txt", "r", stdin );
//freopen( "out.txt", "w", stdout );
while ( scanf( "%d%d", &N, &M ) == )
{
memset( minv, , sizeof(minv) ); sum[] = ;
for ( int i = ; i < N; ++i )
{
scanf( "%I64d", &sum[i] );
sum[i] += sum[i - ];
}
sum[N] = INF; int cnt = ;
for ( int i = ; i < M; ++i )
{
int a, b, c;
scanf( "%d%d%d", &a, &b, &c );
LL tmp;
if ( a > b )
tmp = (LL)c + sum[a - ] - sum[b - ];
else
tmp = (LL)c - sum[b - ] + sum[a - ];
D[cnt].l = a;
D[cnt].r = b;
D[cnt].val = tmp;
D[cnt].id = -;
++cnt;
} int Q;
scanf( "%d", &Q );
for ( int i = ; i < Q; ++i )
{
int a, b;
scanf( "%d%d", &a, &b );
D[cnt].id = i;
D[cnt].val = ;
D[cnt].l = a;
D[cnt].r = b;
++cnt;
} memset( ans, , sizeof(ans) );//之前少了这个,一直WA…好像上组数据会影响到下组数据中u=v的情况
sort( D, D + cnt, cmp ); for ( int i = ; i < cnt; ++i )
{
if ( D[i].l < D[i].r )
{
Add( D[i].r, D[i].val );
if ( D[i].id != - )
ans[ D[i].id ] = sum[ D[i].r - ] - sum[ D[i].l - ] + Query( D[i].r );
}
} for ( int i = ; i <= N; ++i )
minv[i] = one << ; for ( int i = ; i < cnt; ++i )
{
if ( D[i].l > D[i].r )
{
if ( D[i].id == - ) Add( D[i].r, D[i].val );
if ( D[i].id != - )
ans[ D[i].id ] = Query( D[i].r ) - sum[ D[i].l - ] + sum[ D[i].r - ];
}
} for ( int i = ; i < Q; ++i )
printf( "%d\n", (int)ans[i] );
}
return ;
}
ZOJ 3724 Delivery 树状数组好题的更多相关文章
- HDU 1166 敌兵布阵(线段树/树状数组模板题)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- st表树状数组入门题单
预备知识 st表(Sparse Table) 主要用来解决区间最值问题(RMQ)以及维护区间的各种性质(比如维护一段区间的最大公约数). 树状数组 单点更新 数组前缀和的查询 拓展:原数组是差分数组时 ...
- bzoj1103树状数组水题
(卧槽,居然规定了修改的两点直接相连,亏我想半天) 非常水的题,用dfs序(而且不用重复,应该是直接规模为n的dfs序)+树状数组可以轻松水 收获:树状数组一遍A(没啥好骄傲的,那么简单的东西) #i ...
- UESTC 1584 Washi与Sonochi的约定【树状数组裸题+排序】
题目链接:UESTC 1584 Washi与Sonochi的约定 题意:在二维平面上,某个点的ranked被定义为x坐标不大于其x坐标,且y坐标不大于其y坐标的怪物的数量.(不含其自身),要求输出n行 ...
- 敌兵布阵 HDU - 1166 (树状数组模板题,线段树模板题)
思路:就是树状数组的模板题,利用的就是单点更新和区间求和是树状数组的强项时间复杂度为m*log(n) 没想到自己以前把这道题当线段树的单点更新刷了. 树状数组: #include<iostrea ...
- 树状数组训练题1:弱弱的战壕(vijos1066)
题目链接:弱弱的战壕 这道题似乎是vijos上能找到的最简单的树状数组题了. 原来,我有一个错误的思想,我的设计是维护两个树状数组,一个是横坐标,一个是纵坐标,然后读入每个点的坐标,扔进对应的树状数组 ...
- 树状数组 简单题 cf 961E
题目链接 : https://codeforces.com/problemset/problem/961/E One day Polycarp decided to rewatch his absol ...
- 【树状数组 思维题】luoguP3616 富金森林公园
树状数组.差分.前缀和.离散化 题目描述 博艾的富金森林公园里有一个长长的富金山脉,山脉是由一块块巨石并列构成的,编号从1到N.每一个巨石有一个海拔高度.而这个山脉又在一个盆地中,盆地里可能会积水,积 ...
- Lightoj 1112 - Curious Robin Hood 【单点改动 + 单点、 区间查询】【树状数组 水题】
1112 - Curious Robin Hood PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 64 MB ...
随机推荐
- JAVA HTTP连接(HttpURLConnection)中使用代理(Proxy)及其验证(Authentication)
public static void main(String[] args) { // TODO Auto-generated method stub try { URL url = new URL( ...
- 搭建ssm中遇到的问题
1.多模块pom.xml文件无效 原因是没有指定模块
- MVAPICH
from:https://developer.nvidia.com/mvapich MVAPICH2 is an open source implementation of Message Passi ...
- 前端面试整理(HTML&CSS)
1.行内元素和块级元素?img算什么?行内元素怎么转化为块级元素? 行内元素:和有他元素都在一行上,高度.行高及外边距和内边距都不可改变,文字图片的宽度不可改变,只能容纳文本或者其他行内元素:其中im ...
- List<T>转换为二维数组
public <T> Object[][] toArrays(List<T> data){ Object[][] o=new Object[data.size()][20]; ...
- Vue项目架构设计与工程化实践
摘自Berwin<Vue项目架构设计与工程化实践>github.com/berwin/Blog/issues/14 1.Vue依赖套件 vuex:项目复杂后,用vuex来管理状态 elem ...
- Hibernate无法提取结果集
原因:表结构错误或 与 映射文件不一致 org.springframework.dao.InvalidDataAccessResourceUsageException: could not extra ...
- opendaylight安装
OpenDaylight安装 环境 jdk-1.8 maven 环境配置安装 Java环境 查看Java环境 java -version 安装jdk-1.8 yum install java-1.8 ...
- Java OOP——JAVA关键字与保留字说明及使用
1.abstract abstract 关键字可以修改类或方法. abstract 类可以扩展(增加子类),但不能直接实例化. abstract 方法不在声明它的类中实现,但必须在某个子类中重写. - ...
- 正则(re 模块)
就其本质而言,正则表达式(或 RE)是一种小型的.高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现.正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹 ...