题意:给你一个有向图,第一类边是从第i个点到第i+1个点的,还有多出来的m条二类边,是从u到v的,同样是有向的。然后你要处理询问,从u到v经过最多一次二类边的最短距离是多少。

题目我觉得是神题,然后看了网上的一些神解法,其中一个非常neatly,在此说下感想。

首先我们考虑的是(u<v)的所有询问,那么我们可以发现,这个时候所有二类边(u>v)的,是不可能用到的。然后我们想,从u到v的最短距离,就是利用u+1~v中的某个起点的二类边到达某个点k(u<k<=v),所以在计算的时候我们只需要知道这些边里能节省的距离的最小值就可以了。所以当我们把询问离线,我们优先处理的是u大v小的边,然后对于每天边,我们可以更新一下对应的节省了的距离的最小值,然后询问的时候就是两点间的距离+节省距离的最小值。

同样,在处理(u>v)的询问的时候,所有的二类边(u<v)也是不会用到的。然后在询问(v,u)的时候,我们也是要用到的所以在u之后为起点的边,以及以u为起点,终点在v前的边。但是这个时候询问就有点坑爹了,因为我们是从u到达u1,经过一条u1->v1的边,然后从v1到达v,区间顺序如下:(v1,v,u,u1),那么花费究竟什么时候最少呢?我们如何利用u1->v1这条边去更新呢?不难发现,我们实际上的距离其实就是 dis(u1,v1)+cost(u1,v1)-dis(v,u),所以在询问的时候u,v是不起作用的,相当于一个常数,我们需要的只是dis(u1,v1)+cost(u1,v1)最小,所以更新的时候只需要维护这个就好了。至此圆满结束。

值得注意的是bit数组的维护以及更新的顺序。

这道题叫我做我肯定做不会,但是这种离线的思想我觉得太重要了,很多看上去解决不了的数据结构归结起来就是没有合适的离线处理。

#pragma warning(disable:4996)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define ll long long
#define maxn 100000
#define maxm 200000
#define lowbit(k) k&(-k)
using namespace std; struct Node
{
int u,v;
ll d;
int idx; int kind;
bool operator < (const Node &b) const{
if (u == b.u){
if (v == b.v) return kind < b.kind;
else return v < b.v;
}
else return u > b.u;
}
}seg[maxm*2];
int top;
ll d[maxn + 50];
ll sd[maxn + 50];
ll ans[maxm + 50];
ll n, m; ll bit[maxn + 50]; void upd(int x, ll val){
while (x <= n){
bit[x] = min(bit[x], val);
x += lowbit(x);
}
} ll query(int x){
ll res = (1LL) << 60;
while (x){
res = min(res, bit[x]);
x -= lowbit(x);
}
return res;
} int main()
{
while (cin >> n >> m){
for (int i = 1; i <= n - 1; i++){
scanf("%lld", &d[i]);
}
sd[1] = 0;
for (int i = 1; i <= n - 1; i++){
sd[i + 1] = sd[i] + d[i];
}
int ui, vi; ll qi; top = 0;
for (int i = 0; i < m; i++){
scanf("%d%d%lld", &seg[top].u, &seg[top].v, &seg[top].d);
seg[top].idx = i; seg[top].kind = 0;
top++;
}
int q; cin >> q;
for (int i = 0; i < q; i++){
scanf("%d%d", &seg[top].u, &seg[top].v);
seg[top].kind = 1; seg[top].idx = i; top++;
}
sort(seg, seg + top);
memset(ans, 0, sizeof(ans));
memset(bit, 0, sizeof(bit));
for (int i = 0; i < top; i++){
if (seg[i].kind == 0 && seg[i].u < seg[i].v){
upd(seg[i].v, seg[i].d - (sd[seg[i].v] - sd[seg[i].u])); // 节省距离的相反数
}
if (seg[i].kind == 1 && seg[i].u < seg[i].v){
ans[seg[i].idx] = query(seg[i].v) + sd[seg[i].v] - sd[seg[i].u];
}
}
for (int i = 1; i <= n; i++) bit[i] = (1LL << 60);
for (int i = 0; i < top; i++){
if (seg[i].kind == 0 && seg[i].u>seg[i].v){
upd(seg[i].v, seg[i].d + sd[seg[i].u] - sd[seg[i].v]);
}
if (seg[i].kind == 1 && seg[i].u>seg[i].v){
ans[seg[i].idx] = query(seg[i].v) - (sd[seg[i].u] - sd[seg[i].v]);
}
}
for (int i = 0; i < q; i++){
printf("%lld\n", ans[i]);
}
}
return 0;
}

ZOJ3724 Delivery(树状数组??)的更多相关文章

  1. ZOJ 3724 Delivery 树状数组好题

    虽然看起来是求最短路,但因为条件的限制,可以转化为区间求最小值. 对于一条small path [a, b],假设它的长度是len,它对区间[a, b]的影响就是:len-( sum[b]-sum[a ...

  2. BZOJ 1103: [POI2007]大都市meg [DFS序 树状数组]

    1103: [POI2007]大都市meg Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2221  Solved: 1179[Submit][Sta ...

  3. bzoj1878--离线+树状数组

    这题在线做很麻烦,所以我们选择离线. 首先预处理出数组next[i]表示i这个位置的颜色下一次出现的位置. 然后对与每种颜色第一次出现的位置x,将a[x]++. 将每个询问按左端点排序,再从左往右扫, ...

  4. codeforces 597C C. Subsequences(dp+树状数组)

    题目链接: C. Subsequences time limit per test 1 second memory limit per test 256 megabytes input standar ...

  5. BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]

    2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2545  Solved: 1419[Submit][Sta ...

  6. BZOJ 3529: [Sdoi2014]数表 [莫比乌斯反演 树状数组]

    3529: [Sdoi2014]数表 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1399  Solved: 694[Submit][Status] ...

  7. BZOJ 3289: Mato的文件管理[莫队算法 树状数组]

    3289: Mato的文件管理 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 2399  Solved: 988[Submit][Status][Di ...

  8. 【Codeforces163E】e-Government AC自动机fail树 + DFS序 + 树状数组

    E. e-Government time limit per test:1 second memory limit per test:256 megabytes input:standard inpu ...

  9. 【BZOJ-3881】Divljak AC自动机fail树 + 树链剖分+ 树状数组 + DFS序

    3881: [Coci2015]Divljak Time Limit: 20 Sec  Memory Limit: 768 MBSubmit: 508  Solved: 158[Submit][Sta ...

随机推荐

  1. [.NET] 打造防“狼”神器 :任务栏篇

    @微微一笑:本文标题纯属自娱自乐. 隐藏任务栏效果图: 对比 说起来惭愧,上面这个隐藏任务栏功能,只是完成了我一半的预想.本想是可以选择性的隐藏任务栏上的某个TaskBarButton,但是Win7+ ...

  2. Unix 编程

    1. Users and Groups 真实用户ID和真实组ID 真实用户ID和组ID表示运行进程的真实用户 ID 和 组ID. 有效用户ID和有效组IDp 有效 ID 是进程进行相关操作(比如系统调 ...

  3. css权重及优先级问题

    css权重及优先级问题 几个值的对比 初始值 指定值 计算值 应用值 CSS属性的 指定值 (specified value)会通过下面3种途径取得: 在当前文档的样式表中给这个属性赋的值,会被优先使 ...

  4. sed实例一则

    1.背景: test.txt文件里有这些语句 li^E1026^D20150802B07QH800^B698.^C20150801B08CDP00^B514.^C20150803D00A8L00^B2 ...

  5. 九度oj 1523 从上往下打印二叉树

    原题链接:http://ac.jobdu.com/problem.php?pid=1523 建树,再层次遍历bfs.为了找根方便些,加了father指针... 如下: #include<algo ...

  6. iOS8 无法设置定位服务

    针对iOS8系统,需要在plist文件中添加这两个参数 NSLocationAlwaysUsageDescription = YES NSLocationWhenInUseUsageDescripti ...

  7. Linux下如何使CP命令不提示覆盖

    在Linux下使用CP命令,经常会提示是否覆盖,如果是太批量的文件覆盖,老是这么提示,会很烦的.那如何解决这个问题呢? 我们先来看一下原因吧! 一般我们使用的命令是cp -rf sourcefile ...

  8. Spark 3000门徒第一课随笔

    昨晚听了王家林老师的Spark 3000门徒系列课程的第一课,把scala基础过了一遍,对ArrayBuffer有了新的认识: Array本身创建后不可修改ArrayBuffer可修改import s ...

  9. asp.net web.config 经典模式和集成模式相关配置

    <?xml version="1.0"?> <configuration> <!--IIS经典模式下使用--> <system.web&g ...

  10. database first表更新一个表会更新所有的model,包括添加验证代码,解决办法

    因为model类是自动生成的,重新生成后会覆盖自己的修改.一个比较合理做法,就是用 partial class的方式来实现. 比如有一个Model类: Movie.那我们就可以添加一个局部类文件,局部 ...