X 国的地图可以被看作一个两行 nn 列的网格状图。现在 X 国需要修建铁路,然而该国的国王非常小气,他只想保证位于某两列之间的所有城市互相可以到达就行了,在此基础上,他希望所花费的代价最小。

铁路可以建在任何两个相邻的点之间,使他们可以互相到达。可以作为工作人员,你已经整理出了为每一对相邻城市架设铁路所需要的花费。你需要准备好回答国王如下形式的问题。

对于 (i,j)(i,j):当前情况下,使第 ii 列到第 jj 列之间的所有城市连通的最小代价是多少(列下标从 11 开始)?注意不能用其他列的城市。

然而你还有更大的困难,随着时间变化,使用某些边作为铁路的代价会发生改变,你必须有效率地处理这些变化。

输入格式

第一行两个正整数 n,m,表示该国有 2 行 n 列以及 m个询问或者操作。

第二行 3n-2个数,前 n-1个数依次表示在第一行的 n-1 条边上修建铁路的代价。

接下来 n-1 个数,依次表示在第二行的 n-1 条边上修建铁路的代价。

最后 n 个数,依次表示在第 1列到第 n列的边上修建铁路的代价。

接下来 m 行的输入具有如下形式,K,S,T其中

若 K=1,则表示询问当前状态下,使所有第 S 列到第 T 列之间的城市连通需要的最小代价。

若 K=2,则表示位于第 1 行第 S 列的点到第 1 行第 S+1 列的点之间的边上修建铁路的代价变为 T。

若 K=3,则表示位于第 2 行第 S 列的点和第 2 行第 S+1 列的点之间的边上修建铁路的代价变为 T。

若 K=4,则表示第 S 列的边上修建铁路的代价变为 T。

输出格式

依次对每个询问,用一行输出相应的答案。

数据范围与约定

对于 30% 的数据:n,m≤2000。

另有 30% 的数据:所有竖边的代价为 0 且永不改变。

对于全部数据:n,m<10^5

所有输入和输出数据保证合法,且不超过 2^{31}-1

样例输入

4 14
2 3 4 3 1 1 1 5 4 7
1 1 2
1 2 3
1 1 3
1 2 4
2 1 5
1 1 4
4 2 1
1 1 3
1 2 3
1 2 4
3 3 100
1 3 4
1 2 4
1 1 4
样例输出

6
8
10
13
17
9
5
10
15
16
20

暴力显然可以每一次查询做一次最小生成树

一开始贪心,每一列选两个最小的边,用线段树维护,然后选一个最小的未选边

但这样显然不能保证图连通和最优

我们要想办法用数据结构来优化查询和修改,这里用线段树

w[rt][0/1][0/1]表示rt区间左,右是否有竖边的最小值

这样就可以通过左右区间合并来维护和查询

注意当区间只有一个元素时

w[rt][0][1]=a[l]+b[l]+c[l+1]

每一个节点都要算上下一个点的竖边,合并时要减去重复的竖边

详情见代码,这样是可以保证图连通的

s=t时要特判

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long lol;
struct XXX
{
lol a[][];
};
lol w[][][],a[],b[],c[];
int n,m;
void pushup(int rt,int mid)
{int i,j;
for (i=;i<=;i++)
for (j=;j<=;j++)
{
w[rt][i][j]=1e9;
lol cost=w[rt*][i][]+w[rt*+][][j]-c[mid+];
w[rt][i][j]=min(w[rt][i][j],cost);
cost=w[rt*][i][]+w[rt*+][][j]-c[mid+];
w[rt][i][j]=min(w[rt][i][j],cost);
cost=w[rt*][i][]+w[rt*+][][j]-c[mid+];
w[rt][i][j]=min(w[rt][i][j],cost);
}
}
void build(int rt,int l,int r)
{
if (l>r) return;
if (l==r)
{
lol tot=a[l]+b[l]+c[l]+c[l+];
w[rt][][]=tot-c[l+];
w[rt][][]=tot-(a[l]+b[l]+abs(b[l]-a[l]))/;
w[rt][][]=1e9;
w[rt][][]=tot-c[l];
return;
}
int mid=(l+r)/;
build(rt*,l,mid);
build(rt*+,mid+,r);
pushup(rt,mid);
}
void ask(int rt,int l,int r,int L,int R,XXX &p)
{int i,j;
if (l>r) return;
if (l>=L&&r<=R)
{
for (i=;i<=;i++)
for (j=;j<=;j++)
p.a[i][j]=w[rt][i][j];
return;
}
XXX p1,p2;
if (l==r) return;
int mid=(l+r)/;
if (L>=mid+)
{
ask(rt*+,mid+,r,L,R,p2);
for (i=;i<=;i++)
for (j=;j<=;j++)
p.a[i][j]=p2.a[i][j];
return;
}
if (R<=mid)
{
ask(rt*,l,mid,L,R,p1);
for (i=;i<=;i++)
for (j=;j<=;j++)
p.a[i][j]=p1.a[i][j];
return;
}
ask(rt*,l,mid,L,R,p1);
ask(rt*+,mid+,r,L,R,p2);
for (i=;i<=;i++)
for (j=;j<=;j++)
{
p.a[i][j]=1e9;
lol cost=p1.a[i][]+p2.a[][j]-c[mid+];
p.a[i][j]=min(p.a[i][j],cost);
cost=p1.a[i][]+p2.a[][j]-c[mid+];
p.a[i][j]=min(p.a[i][j],cost);
cost=p1.a[i][]+p2.a[][j]-c[mid+];
p.a[i][j]=min(p.a[i][j],cost);
}
}
void update(int rt,int l,int r,lol k,lol x,lol d)
{
if (l>r) return;
if (l==r)
{
if (k==) a[x]=d;
if (k==) b[x]=d;
if (k==) c[x]=d;
lol tot=a[l]+b[l]+c[l]+c[l+];
w[rt][][]=tot-c[l+];
w[rt][][]=tot-(a[l]+b[l]+abs(b[l]-a[l]))/;
w[rt][][]=1e9;
w[rt][][]=tot-c[l];
return;
}
int mid=(l+r)/;
if (k==)
{
if (x<=mid+) update(rt*,l,mid,k,x,d);
if (x>=mid+) update(rt*+,mid+,r,k,x,d);
}
else
{
if (x<=mid) update(rt*,l,mid,k,x,d);
else update(rt*+,mid+,r,k,x,d);
}
pushup(rt,mid);
}
int main()
{int i;
lol k,s,t;
XXX p;
cin>>n>>m;
for (i=;i<=n-;i++)
scanf("%lld",&a[i]);
for (i=;i<=n-;i++)
scanf("%lld",&b[i]);
for (i=;i<=n;i++)
scanf("%lld",&c[i]);
build(,,n-);
while (m--)
{lol ans=2e9;
scanf("%lld%lld%lld",&k,&s,&t);
if (k==)
{
if (s==t)
{printf("%lld\n",c[s]);continue;}
ask(,,n-,s,t-,p);
ans=min(min(p.a[][],p.a[][]),min(p.a[][],p.a[][]));
printf("%lld\n",ans);
}
else
{
update(,,n-,k,s,t);
}
}
}
 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long lol;
struct XXX
{
lol a[][];
};
lol w[][][],a[],b[],c[];
int n,m;
void pushup(int rt,int mid)
{int i,j;
for (i=;i<=;i++)
for (j=;j<=;j++)
{
w[rt][i][j]=1e9;
lol cost=w[rt*][i][]+w[rt*+][][j]-c[mid+];
w[rt][i][j]=min(w[rt][i][j],cost);
cost=w[rt*][i][]+w[rt*+][][j]-c[mid+];
w[rt][i][j]=min(w[rt][i][j],cost);
cost=w[rt*][i][]+w[rt*+][][j]-c[mid+];
w[rt][i][j]=min(w[rt][i][j],cost);
}
}
void build(int rt,int l,int r)
{
if (l>r) return;
if (l==r)
{
lol tot=a[l]+b[l]+c[l]+c[l+];
w[rt][][]=tot-c[l+];
w[rt][][]=tot-(a[l]+b[l]+abs(b[l]-a[l]))/;
w[rt][][]=1e9;
w[rt][][]=tot-c[l];
return;
}
int mid=(l+r)/;
build(rt*,l,mid);
build(rt*+,mid+,r);
pushup(rt,mid);
}
void ask(int rt,int l,int r,int L,int R,XXX &p)
{int i,j;
if (l>r) return;
if (l>=L&&r<=R)
{
for (i=;i<=;i++)
for (j=;j<=;j++)
p.a[i][j]=w[rt][i][j];
return;
}
XXX p1,p2;
if (l==r) return;
int mid=(l+r)/;
if (L>=mid+)
{
ask(rt*+,mid+,r,L,R,p2);
for (i=;i<=;i++)
for (j=;j<=;j++)
p.a[i][j]=p2.a[i][j];
return;
}
if (R<=mid)
{
ask(rt*,l,mid,L,R,p1);
for (i=;i<=;i++)
for (j=;j<=;j++)
p.a[i][j]=p1.a[i][j];
return;
}
ask(rt*,l,mid,L,R,p1);
ask(rt*+,mid+,r,L,R,p2);
for (i=;i<=;i++)
for (j=;j<=;j++)
{
p.a[i][j]=1e9;
lol cost=p1.a[i][]+p2.a[][j]-c[mid+];
p.a[i][j]=min(p.a[i][j],cost);
cost=p1.a[i][]+p2.a[][j]-c[mid+];
p.a[i][j]=min(p.a[i][j],cost);
cost=p1.a[i][]+p2.a[][j]-c[mid+];
p.a[i][j]=min(p.a[i][j],cost);
}
}
void update(int rt,int l,int r,lol k,lol x,lol d)
{
if (l>r) return;
if (l==r)
{
if (k==) a[x]=d;
if (k==) b[x]=d;
if (k==) c[x]=d;
lol tot=a[l]+b[l]+c[l]+c[l+];
w[rt][][]=tot-c[l+];
w[rt][][]=tot-(a[l]+b[l]+abs(b[l]-a[l]))/;
w[rt][][]=1e9;
w[rt][][]=tot-c[l];
return;
}
int mid=(l+r)/;
if (k==)
{
if (x<=mid+) update(rt*,l,mid,k,x,d);
if (x>=mid+) update(rt*+,mid+,r,k,x,d);
}
else
{
if (x<=mid) update(rt*,l,mid,k,x,d);
else update(rt*+,mid+,r,k,x,d);
}
pushup(rt,mid);
}
int main()
{int i;
lol k,s,t;
XXX p;
cin>>n>>m;
for (i=;i<=n-;i++)
scanf("%lld",&a[i]);
for (i=;i<=n-;i++)
scanf("%lld",&b[i]);
for (i=;i<=n;i++)
scanf("%lld",&c[i]);
build(,,n-);
while (m--)
{lol ans=2e9;
scanf("%lld%lld%lld",&k,&s,&t);
if (k==)
{
if (s==t)
{printf("%lld\n",c[s]);continue;}
ask(,,n-,s,t-,p);
ans=min(min(p.a[][],p.a[][]),min(p.a[][],p.a[][]));
printf("%lld\n",ans);
}
else
{
update(,,n-,k,s,t);
}
}
}

计蒜客NOIP模拟赛(3)D1T3 任性的国王的更多相关文章

  1. 计蒜客NOIP模拟赛4 D1T3 小X的佛光

    小 X 是远近闻名的学佛,平日里最喜欢做的事就是蒸发学水. 小 X 所在的城市 X 城是一个含有 N 个节点的无向图,同时,由于 X 国是一个发展中国家,为了节约城市建设的经费,X 国首相在建造 X ...

  2. 计蒜客NOIP模拟赛(2)D1T3 深黑幻想

    [问题描述]    凡终于发愤图强,决定专心搞OI,不再玩纸牌和坑钱了!没过多久就飘飘然了,总是陷入自己进了集训队的深黑幻想之中.    样听说了之后,决定考一考凡欧拉回路怎么写.样:“我给你出一道题 ...

  3. 计蒜客NOIP模拟赛6 D1T1Diamond-square

    Diamond-square 算法是一种能够用于生成噪声的算法,现在我们考虑这个算法的一个变种. 你有一个 2^n\times 2^n2​n​​×2​n​​ 的网格,一共有 (2^n+1)^2(2​n ...

  4. 计蒜客NOIP模拟赛4 D2T1 鬼脚图

    鬼脚图,又称画鬼脚,在日本称作阿弥陀签,是一种经典游戏,也是一种简易的决策方法,常常用来抽签或决定分配组合. 下图就是一张鬼脚图,其包含若干条竖线和若干条横线.请注意,横线只能水平连接相邻的两条竖线, ...

  5. 计蒜客 NOIP模拟赛(3) D1T1火山喷发

    火山喷发对所有附近的生物具有毁灭性的影响.在本题中,我们希望用数值来模拟这一过程. 在环境里有 nnn 个生物分别具有 A1,A2,⋯,An​​点生命值,一次火山喷发总计 M轮,每轮造成 1点伤害,等 ...

  6. 计蒜客NOIP模拟赛(2) D1T1邻家男孩

    凡是一个具有领导力的孩子.现实生活中他特别喜欢玩一个叫做 UNO 的纸牌游戏,他也总是带着其他小朋友一起玩,然后战胜他们.慢慢地,他厌倦了胜利,于是准备发明一种新的双人纸牌游戏. 初始时,每个人手中都 ...

  7. 计蒜客NOIP模拟赛5 D1T1 机智的 AmyZhi

    那年一个雨季,AmyZhi 在校门外弯身买参考书. 这时 SiriusRen 走过来,一言不合甩给她一道“自认为”很难的题: --------------- 给你一个数字 NN(NN 的范围是 11  ...

  8. 计蒜客NOIP模拟赛4 D2T2 跑步爱天天

    YOUSIKI 在 noip2016 的一道<天天爱跑步>的题爆零后,潜心研究树上问题,成为了一代大师,于是皮皮妖为了测验他,出了一道题,名曰<跑步爱天天>. 有一个以 1 为 ...

  9. 计蒜客NOIP模拟赛4 D1T2小X的密室

    小 X 正困在一个密室里,他希望尽快逃出密室. 密室中有 N 个房间,初始时,小 X 在 1 号房间,而出口在 N 号房间. 密室的每一个房间中可能有着一些钥匙和一些传送门,一个传送门会单向地创造一条 ...

随机推荐

  1. centos7 下通过nginx+uwsgi部署django应用

    1. 安装python3.6 1. 获取 wget https://www.python.org/ftp/python/3.6.2/Python-3.6.2.tgz tar -xzvf Python- ...

  2. JAVA使用和操作properties文件

    java中的properties文件是一种配置文件,主要用于表达配置信息,文件类型为*.properties,格式为文本文件,文件的内容是格式是"键=值"的格式,在properti ...

  3. JavaScript 相关知识

    一.数组   var a = [1,2,3,4]; console.log(a.length); a.push(5); console.log(a); // [1, 2, 3, 4, 5] var r ...

  4. 自主学习之RxSwift(二) -----flatMap

    最近项目中有这么一个需求,下面是三个网络请求 A.从服务器获取到时间戳(GET 方法,获取 timeLine) B.进行用户头像上传,获得回传的URL(POST方法,参数为 userId, timeL ...

  5. Project facet is Java version 1.7 is not spported

    在移植eclipse项目时,如果遇到 "Project facet Java version 1.7 is not supported." 项目中的jdk1.7不支持.说明项目是其 ...

  6. python之路--day11---迭代器和生成器

    迭代: 迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值 为什么要有迭代器: 数据类型的取值,字符串,列表,元组依靠索引可以取值,但是字典,集合,文件这些数据类型无法 ...

  7. 构建自己的PHP框架--构建模版引擎(3)

    之前我们实现了最简单的echo命令的模版替换,就是将{{ $name }}这样一段内容替换成<?php echo $name ?>. 现在我们来说下其他的命令,先来回顾下之前的定义 输出变 ...

  8. GIT入门笔记(2)- 典型的工作模式

      分布式相比于集中式的最大区别在于开发者可以提交到本地,每个开发者通过克隆(git clone),在本地机器上拷贝一个完整的Git仓库.   下图是经典的git开发过程.   Git的功能特性:   ...

  9. C#微信公众号——自定义菜单

    自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单.一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“...”代替.自定义菜单的介绍,可以看官方开发文档http://mp. ...

  10. Java-NIO(七):阻塞IO与非阻塞IO

    阻塞IO 传统的 IO 流都是阻塞式的. 也就是说,当一个线程调用 read() 或 write()时,该线程被阻塞,直到有一些数据被读取或写入,该线程在此期间不能执行其他任务. 因此,在完成网络通信 ...