虽然看起来是求最短路,但因为条件的限制,可以转化为区间求最小值。

对于一条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 树状数组好题的更多相关文章

  1. HDU 1166 敌兵布阵(线段树/树状数组模板题)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  2. st表树状数组入门题单

    预备知识 st表(Sparse Table) 主要用来解决区间最值问题(RMQ)以及维护区间的各种性质(比如维护一段区间的最大公约数). 树状数组 单点更新 数组前缀和的查询 拓展:原数组是差分数组时 ...

  3. bzoj1103树状数组水题

    (卧槽,居然规定了修改的两点直接相连,亏我想半天) 非常水的题,用dfs序(而且不用重复,应该是直接规模为n的dfs序)+树状数组可以轻松水 收获:树状数组一遍A(没啥好骄傲的,那么简单的东西) #i ...

  4. UESTC 1584 Washi与Sonochi的约定【树状数组裸题+排序】

    题目链接:UESTC 1584 Washi与Sonochi的约定 题意:在二维平面上,某个点的ranked被定义为x坐标不大于其x坐标,且y坐标不大于其y坐标的怪物的数量.(不含其自身),要求输出n行 ...

  5. 敌兵布阵 HDU - 1166 (树状数组模板题,线段树模板题)

    思路:就是树状数组的模板题,利用的就是单点更新和区间求和是树状数组的强项时间复杂度为m*log(n) 没想到自己以前把这道题当线段树的单点更新刷了. 树状数组: #include<iostrea ...

  6. 树状数组训练题1:弱弱的战壕(vijos1066)

    题目链接:弱弱的战壕 这道题似乎是vijos上能找到的最简单的树状数组题了. 原来,我有一个错误的思想,我的设计是维护两个树状数组,一个是横坐标,一个是纵坐标,然后读入每个点的坐标,扔进对应的树状数组 ...

  7. 树状数组 简单题 cf 961E

    题目链接 : https://codeforces.com/problemset/problem/961/E One day Polycarp decided to rewatch his absol ...

  8. 【树状数组 思维题】luoguP3616 富金森林公园

    树状数组.差分.前缀和.离散化 题目描述 博艾的富金森林公园里有一个长长的富金山脉,山脉是由一块块巨石并列构成的,编号从1到N.每一个巨石有一个海拔高度.而这个山脉又在一个盆地中,盆地里可能会积水,积 ...

  9. Lightoj 1112 - Curious Robin Hood 【单点改动 + 单点、 区间查询】【树状数组 水题】

    1112 - Curious Robin Hood PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 64 MB ...

随机推荐

  1. assert函数和捕获异常

    assert函数: C语言和C++都有一个专为调试而准备的工具函数,就是 assert()函数. 这个函数是在C语言的 assert.h 库文件里定义的,所以包含到C++程序里我们用以下语句: #in ...

  2. MySQL与SQLServer的区别(一千条语句)

    ER图.分页.差异.Java连接MySQL SELECT * FROM table LIMIT [offset,] rows | rows OFFSET offset LIMIT 子句可以被用于强制 ...

  3. 利用Kettle转储接口数据

    1.     项目背景 1.1.  项目背景 数据接口 API:应用程序接口(Application Program Interface)的简称,是实现计算机软件之间数据通信的工具.同时API也是一种 ...

  4. java循环删除List元素的方法总结

    1.for循环 2.迭代器 3.过渡法 import java.util.*; /** * Created by HP on 2018/8/2. */ public class Test { publ ...

  5. HDU 2047 EOF牛肉串

    水到不想整理,线性DP #include <algorithm> #include <iostream> #include <cstring> #include & ...

  6. 解决mysql远程连接失败的问题

    问题描述 在我远程连接我的服务器数据库的时候,navicat给我提示了这么一个错误: ERROR : Host 'xxx' is not allowed to connect to thisMySQL ...

  7. spring-bean(注解方式-管理及依赖注入)

    Bean管理(注解方式) 1.添加注解的依赖包:Spring-aop.jar 2.配置spring的XML文件的引入(查官方源码) 3.开启注解的扫描 <context:component-sc ...

  8. Liunx 配置sshd服务

    简介 SSH(Secure Shell)是一种能够提供安全远程登录会话的协议,也是目前远程管理Linux系统最首选的方式,因为传统的ftp或telnet服务是不安全的,它们会把帐号口令和数据资料等数据 ...

  9. git--分布式版本管理系统

    参考博客:廖雪峰的官方网站 一.window安装git Git官网直接下载安装程序,默认选项安装即可. 1.设置自己的git(cmd命令或者git bash进入) git config --globa ...

  10. PHP获取异常信息

    try { } catch (\Exception $e) { $extra = [ 'code' => $e->getCode(), 'msg' => $e->getMess ...