题意:给你一个有向图,第一类边是从第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. XSS的原理分析与解剖[转http://www.freebuf.com/articles/web/40520.html]

    0×01 前言: <xss攻击手法>一开始在互联网上资料并不多(都是现成的代码,没有从基础的开始),直到刺的<白帽子讲WEB安全>和cn4rry的<XSS跨站脚本攻击剖析 ...

  2. EMVTag系列13《脱机PIN》

    DGI8010用于个人化借记贷记交易中使用的脱机PIN.数据强制要求加密.制卡数据传输过程中,此DGI采用DEK加密保护. 数据分组标识 '8010'的数据内容       要求            ...

  3. oracle11g 数据文件误删恢复(无备份)

    OS: Oracle Linux Server release 5.7 DB: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - ...

  4. bc命令

    bc 命令:     bc 命令是用于命令行计算器. 它类似基本的计算器. 使用这个计算器可以做基本的数学运算. [tough@localhost *|bc [tough@localhost expr ...

  5. iOS-添加测试设备Identifier

    第一步:确认你的设备已经连接 第二步:点击xcode上"Windows"标签,选择"Devices" 第三步:在弹出的左框选择你要添加的设备.在右边框里可以找到 ...

  6. iOS学习之Object-C语言类的扩展

    一.Category      1.Category:也叫分类,类目.是为没有源代码的类扩充功能.扩充的功能会成为原有类的一部分,可以通过原有类或者原有的对象直接调用,并且可继承.      2.注意 ...

  7. centos下各种c++库文件的安装

    Centos编译boost   1.下载最新的boost http://www.boost.org/   2.解压文件 tar -xzvf boost_1_45_0.tar.gz    3.编译bja ...

  8. [shell基础]——sed命令

    关于sed sed 是一种在线编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓 ...

  9. SQL Server 2008 没有可用于 charge_sys_Log.LDF 的编辑器

    因为上网问题重新装了系统.今天在整 SQL Server  的时候出现了这样一个问题. 因为之前装 SQL Server  的时候没有遇到过这种情况,感觉很新奇.所以详细的记录一下,希望对别人能有一定 ...

  10. Android -- 经验分享(二)

    目录                                                                                   自定义两个View进行画图,让 ...