【CodeChef】Querying on a Grid(分治,最短路)
【CodeChef】Querying on a Grid(分治,最短路)
题面
题解
考虑分治处理这个问题,每次取一个\(mid\),对于\(mid\)上的三个点构建最短路径树(因为保证了最短路唯一所以是树)。
如果两点之间的最短路径跨越了\(mid\),那么必定有\(dis[u]+dis[v]\)的和就是最短路径长度。
那么我们在分治过程中考虑每一个\(mid\),取其中\(dis[u]+dis[v]\)的最小值,这样子就很容易可以找到最短路径长度。
然后知道了最短路径长度怎么找到最短路径呢?
我们已经把最短路径树给构出来了,那么只需要在必定跨越的\(mid\)的最短路径树上做修改就好了。
如果直接链加再单点询问,这样子是两个\(log\)的,改成单点修改,子树求和就可以做到一个\(log\)了。
这样子分治+对于每个最短路径树计算答案,复杂度是\(O(nlog^2n)\),似乎还有一个\(3\)的常数。
c++11真好用,写着写着就跟zsy代码一样了(大雾
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define MAX 300300
#define pi pair<ll,int>
#define fr first
#define sd second
#define mp make_pair
#define pb push_back
inline ll read()
{
ll x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
vector<pi> E[MAX];
int n,m,Q;
int id[MAX][3],tot;
int lb(int x){return x&(-x);}
struct SPT
{
ll dis[MAX],c[MAX];int fa[MAX],dfn[MAX],low[MAX],tim;
bool vis[MAX];
vector<int> son[MAX];
priority_queue<pi,vector<pi>,greater<pi> >Q;
void dfs(int u){dfn[u]=++tim;for(int v:son[u])dfs(v);low[u]=tim;}
void Modify(int x,ll w){x=dfn[x];while(x<=tim)c[x]+=w,x+=lb(x);}
ll Query(int x)
{
ll ret=0;int X;
X=low[x];while(X)ret+=c[X],X-=lb(X);
X=dfn[x]-1;while(X)ret-=c[X],X-=lb(X);
return ret;
}
void Dijkstra(int l,int r,int S)
{
for(int i=l;i<=r;++i)dis[i]=1e18,vis[i]=false;
dis[S]=0;Q.push(mp(dis[S],S));
while(!Q.empty())
{
int u=Q.top().sd;Q.pop();
if(vis[u])continue;vis[u]=true;
for(pi x:E[u])
{
int v=x.sd;ll w=x.fr;
if(v<l||v>r||dis[v]<=dis[u]+w)continue;
dis[v]=dis[u]+w;fa[v]=u;Q.push(mp(dis[v],v));
}
}
for(int i=l;i<=r;++i)if(i!=S)son[fa[i]].pb(i);
dfs(S);
}
}T[18][3];
void Build(int l,int r,int dep)
{
int mid=(l+r)>>1;
for(int i=0;i<n;++i)
T[dep][i].Dijkstra(id[l][0],id[r][n-1],id[mid][i]);
if(l<mid)Build(l,mid-1,dep+1);
if(r>mid)Build(mid+1,r,dep+1);
}
ll mx;
void Calc(int l,int r,int dep,int x,int y)
{
int mid=(l+r)>>1;
for(int i=0;i<n;++i)
mx=min(mx,T[dep][i].dis[x]+T[dep][i].dis[y]);
if(x<=id[mid][n-1]&&y>=id[mid][0])return;
if(y<id[mid][0])Calc(l,mid-1,dep+1,x,y);
else Calc(mid+1,r,dep+1,x,y);
}
void Modify(int l,int r,int dep,int x,int y,ll w)
{
int mid=(l+r)>>1;
for(int i=0;i<n;++i)
if(T[dep][i].dis[x]+T[dep][i].dis[y]==mx)
{
T[dep][i].Modify(x,w),T[dep][i].Modify(y,w);
return;
}
if(y<id[mid][0])Modify(l,mid-1,dep+1,x,y,w);
else Modify(mid+1,r,dep+1,x,y,w);
}
ll Query(int l,int r,int dep,int u)
{
int mid=(l+r)>>1;ll ret=0;
for(int i=0;i<n;++i)
{
ll s=T[dep][i].Query(u);
if(id[mid][i]==u)s>>=1;
ret+=s;
}
if(u<id[mid][0])ret+=Query(l,mid-1,dep+1,u);
if(u>id[mid][n-1])ret+=Query(mid+1,r,dep+1,u);
return ret;
}
int main()
{
n=read();m=read();Q=read();
for(int i=0;i<m;++i)
for(int j=0;j<n;++j)id[i][j]=++tot;
for(int i=0;i<n-1;++i)
for(int j=0;j<m;++j)
{
int u=id[j][i],v=id[j][i+1];ll w=read();
E[u].pb(mp(w,v));E[v].pb(mp(w,u));
}
for(int i=0;i<n;++i)
for(int j=0;j<m-1;++j)
{
int u=id[j][i],v=id[j+1][i];ll w=read();
E[u].pb(mp(w,v));E[v].pb(mp(w,u));
}
Build(0,m-1,0);
while(Q--)
{
int opt=read();
if(opt==1)
{
int x1=read()-1,y1=read()-1,x2=read()-1,y2=read()-1;ll w=read();
int u=id[y1][x1],v=id[y2][x2];if(u>v)swap(u,v);
mx=1e18;Calc(0,m-1,0,u,v);
Modify(0,m-1,0,u,v,w);
}
else
{
int x=read()-1,y=read()-1,u=id[y][x];
printf("%lld\n",Query(0,m-1,0,u));
}
}
return 0;
}
【CodeChef】Querying on a Grid(分治,最短路)的更多相关文章
- 【BZOJ-4456】旅行者 分治 + 最短路
4456: [Zjoi2016]旅行者 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 254 Solved: 162[Submit][Status] ...
- BZOJ4456/UOJ#184[Zjoi2016]旅行者 分治 最短路
原文链接http://www.cnblogs.com/zhouzhendong/p/8682133.html 题目传送门 - BZOJ4456 题目传送门 - UOJ#184 题意 $n\times ...
- [BZOJ4456] [Zjoi2016]旅行者 分治+最短路
4456: [Zjoi2016]旅行者 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 777 Solved: 439[Submit][Status] ...
- 【BZOJ4456】[Zjoi2016]旅行者 分治+最短路
[BZOJ4456][Zjoi2016]旅行者 Description 小Y来到了一个新的城市旅行.她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北的道路,这些道路两两相交形 ...
- hdu 4871 树的分治+最短路记录路径
/* 题意:给你一些节点和一些边,求最短路径树上是k个节点的最长的路径数. 解:1.求出最短路径树--spfa加记录 2.树上进行操作--树的分治,分别处理子树进行补集等运算 */ #include& ...
- [BZOJ4456][ZJOI2016]旅行者:分治+最短路
分析 类似于点分治的思想,只统计经过分割线的最短路,然后把地图一分为二. 代码 #include <bits/stdc++.h> #define rin(i,a,b) for(regist ...
- P2993 [FJOI2014]最短路径树问题 点分治+最短路
这道题还是非常简单的,由于我们要保证最小字典序,因此我们需要把边进行排序,然后从大到小插入,因为链式前向星是倒着存的.我们只需要先跑一个最短路,然后查询边是不是在最短路上,这个可以通过枚举边并用 di ...
- 【CodeChef】LECOINS(同余最短路,背包DP)
题意:给定n个物品,每个物品可以取无限次,每个物品有两种属性:价值v和颜色c 现在有q个询问,每次询问是否能取出价值和为S的方案,如有多解输出不同颜色种数的最大值 题意:看到BZOJ评论区有好心人说C ...
- BSOJ5458 [NOI2018模拟5]三角剖分Bsh 分治最短路
题意简述 给定一个正\(n\)边形及其三角剖分,每条边的长度为\(1\),给你\(q\)组询问,每次询问给定两个点\(x_i\)至\(y_i\)的最短距离. 做法 显然正多边形的三角剖分是一个平面图, ...
随机推荐
- sso单点登录系统(解决session共享)
场景:假设一个用户将自己的登录信息提交到后台,如果session保存的信息分布在多台机器上,并且不共享,那么可能导致用户的登录信息出现短暂的丢失,为什么这样讲,因为用户访问服务器中间还要经过负载均衡服 ...
- 我们为什么要使用List和Set(List,Set详解)
1.集合概述 类图 集合和数组的区别? 集合基本方法 集合特有的遍历方式? public static void main(String[] args) { //创建集合对象 Collection c ...
- 消除element.style { }
1.在写前台页面时,我们会发现控制台里会自动出现一些样式覆盖掉我们定义的样式: 解决的办法: 把被覆盖的样式单独定义出来,并在样式后面加上 !important,表示高优先级.
- EF内容记录_EF连接Mysql版本问题
EF连接MySQL可用版本,由于EF.MySQLConnection.mysql-for-visualstudio.VS版本.MySQL.Data.MySQL.Data.Entity版本问题较花时间, ...
- vue学习的笔记补充
// vue-router中可以使用 routes:[ { path:'/', name:'index', component:()=>import('./index') } ] // 这种写法 ...
- ToroiseGit提交代码上传到阿里云的Gitlab
https://blog.csdn.net/xiaomogg/article/details/51903004(copy) 准备 具体过程 准备 1.拥有一个GitHub账户 2.安装了Tortois ...
- flutter开发vscode用模拟器调试
android studio的太重,我装的是android sdk,使用avd的模拟器启动黑屏 启动夜神模拟器(已卸载) 建立连接: adb connect 127.0.0.1:62001 (夜 ...
- B站弹幕姬(🐔)分析与开发(上篇)
辞职之后 休息了一段时间,最近准备开始恢复去工作的状态了,所以搞点事情来练练手.由于沉迷b站女妆大佬想做个收集弹幕的然后根据弹幕自动回复一些弹幕的东西.网上搜了一下有个c#的版本,感觉还做得不错,于是 ...
- 浅谈WPF的VisualBrush
首先看看VisualBrush的解释,msdn上面的解释是使用 Visual 绘制区域,那么我们再来看看什么是Visual呢?官方的解释是:获取或设置画笔的内容,Visual 是直接继承自Depend ...
- Python 常用模块总结
模块的分类: 1.内置模块(python自带的比如像os,sys等模块) 2.自定义模块,自己写的一些模块 3.第三方模块(开源模块) 模块导入: 1.import sys ...