[BZOJ 3995] [SDOI2015] 道路修建 【线段树维护连通性】

时间:2022-09-16 23:34:43

题目链接:BZOJ - 3995

题目分析

这道题..是我悲伤的回忆..

线段树维护连通性,与 BZOJ-1018 类似,然而我省选之前并没有做过  1018,即使它在 ProblemSet 的第一页。

更悲伤的是,这道题有 40 分的暴力分,写个 Kruskal 就可以得到,然而我写了个更快的 DP 。

这本来没有什么问题,然而我的 DP 转移少些了一种情况,于是...爆零。没错,省选前20名可能就我没有得到这 40 分?

不想再多说什么了...希望以后不要再这样 SB 了,如果以后还有机会的话。

还是来说这道题吧。

首先 Orz lzr 神犇,我写的是他的做法。

对于一段区间,我们只需要知道它四个角上的四个格点之间的连通性就可以了,一共有 10 种可能的情况,然而这 10 种情况里有一些是同一种类的,于是可以分为 5 种。

然后注意划分区间的时候是选图中的红色格子,而不是选用题目直接描述的黑色格子。即长度为 1 的区间其实包含了 2 * 2 的 4 个格点。

[BZOJ 3995] [SDOI2015] 道路修建 【线段树维护连通性】

这样的好处是,非常好写!用两个子区间合成一个新区间的答案时,左区间的右端点和右区间的左端点其实是同一列格点,是重合的,无缝对接,所以只要两端区间的联通状态确定了,整个区间的联通状态也就确定了。

不像另一种做法,还要考虑合并时中间的连边情况,非常非常非常复杂。

这样合并最多就 5 * 5 = 25 种,实际上有些合并是不合法的,最后只有 17 种合并。将它们手动写到一个表里就好了。

然后用线段树维护就好了,当修改一条竖边的边权时,相邻的两个格子都要重新计算。

代码

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm> using namespace std; inline void Read(int &Num)
{
char c = getchar();
bool Neg = false;
while (c < '0' || c > '9')
{
if (c == '-') Neg = true;
c = getchar();
}
Num = c - '0'; c = getchar();
while (c >= '0' && c <= '9')
{
Num = Num * 10 + c - '0';
c = getchar();
}
if (Neg) Num = -Num;
} inline int gmin(int a, int b) {return a < b ? a : b;}
inline int gmax(int a, int b) {return a > b ? a : b;} const int MaxN = 60000 + 5, INF = 999999999;
const int Magic[20][5] = {
{1, 1, 1}, {1, 2, 2}, {1, 3, 3}, {1, 4, 4},
{1, 5, 5}, {2, 1, 2}, {2, 3, 2}, {2, 5, 4},
{3, 1, 3}, {3, 3, 3}, {3, 5, 5}, {4, 1, 4},
{4, 2, 2}, {4, 4, 4}, {5, 1, 5}, {5, 2, 3},
{5, 4, 5}
}; int n, m;
int A[MaxN][3]; struct ES
{
int X[6];
} T[MaxN * 4]; ES operator + (ES e1, ES e2)
{
ES ret;
for (int i = 1; i <= 5; ++i) ret.X[i] = INF;
for (int i = 0; i < 17; ++i)
ret.X[Magic[i][2]] = gmin(ret.X[Magic[i][2]], e1.X[Magic[i][0]] + e2.X[Magic[i][1]]);
return ret;
} ES Calc(int s)
{
ES ret;
ret.X[1] = A[s][1] + A[s][2];
ret.X[2] = A[s][1] + A[s][2] + A[s][0] + A[s + 1][0] - gmax(gmax(A[s][1], A[s][2]), gmax(A[s][0], A[s + 1][0]));
ret.X[3] = A[s + 1][0] + gmin(A[s][1], A[s][2]);
ret.X[4] = A[s][0] + gmin(A[s][1], A[s][2]);
ret.X[5] = gmin(A[s][1], A[s][2]);
return ret;
} void Build(int x, int s, int t)
{
if (s == t)
{
T[x] = Calc(s);
return;
}
int m = (s + t) >> 1;
Build(x << 1, s, m);
Build(x << 1 | 1, m + 1, t);
T[x] = T[x << 1] + T[x << 1 | 1];
} void Change(int x, int s, int t, int Pos)
{
if (s == t)
{
T[x] = Calc(s);
return;
}
int m = (s + t) >> 1;
if (Pos <= m) Change(x << 1, s, m, Pos);
else Change(x << 1 | 1, m + 1, t, Pos);
T[x] = T[x << 1] + T[x << 1 | 1];
} ES Get(int x, int s, int t, int l, int r)
{
if (l <= s && r >= t) return T[x];
int m = (s + t) >> 1;
ES ret;
if (r <= m) ret = Get(x << 1, s, m, l, r);
else if (l >= m + 1) ret = Get(x << 1 | 1, m + 1, t, l, r);
else ret = Get(x << 1, s, m, l, r) + Get(x << 1 | 1, m + 1, t, l, r);
return ret;
} int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n - 1; ++i) Read(A[i][1]);
for (int i = 1; i <= n - 1; ++i) Read(A[i][2]);
for (int i = 1; i <= n; ++i) Read(A[i][0]);
Build(1, 1, n - 1);
char Str[3];
ES Ans;
int x, y, xx, yy, Num, l, r;
for (int i = 1; i <= m; ++i)
{
scanf("%s", Str);
if (Str[0] == 'C')
{
Read(x); Read(y); Read(xx); Read(yy); Read(Num);
if (x == xx)
{
A[gmin(y, yy)][x] = Num;
Change(1, 1, n - 1, gmin(y, yy));
}
else
{
A[y][0] = Num;
if (y != 1) Change(1, 1, n - 1, y - 1);
if (y != n) Change(1, 1, n - 1, y);
}
}
else
{
Read(l); Read(r);
if (l == r) printf("%d\n", A[l][0]);
else
{
Ans = Get(1, 1, n - 1, l, r - 1);
printf("%d\n", Ans.X[2]);
}
}
}
return 0;
}

  

[BZOJ 3995] [SDOI2015] 道路修建 【线段树维护连通性】的更多相关文章

  1. 【BZOJ3995】&lbrack;SDOI2015&rsqb;道路修建 线段树区间合并

    [BZOJ3995][SDOI2015]道路修建 Description  某国有2N个城市,这2N个城市构成了一个2行N列的方格网.现在该国*有一个旅游发展计划,这个计划需要选定L.R两列(L&l ...

  2. &lbrack;bzoj3995&rsqb; &lbrack;SDOI2015&rsqb;道路修建 线段树

    Description 某国有2N个城市,这2N个城市构成了一个2行N列的方格网.现在该国*有一个旅游发展计划,这个计划需要选定L.R两列(L<=R),修建若干条专用道路,使得这两列之间(包括 ...

  3. &lbrack;SDOI2015&rsqb;道路修建&lpar;线段树&rpar;

    题意:给定2行n列的四连通带权网格图,支持修改边权和查询第[l,r]列的最小生成树 题解:这是一道好题,要么SDOI2019中n=2的20pts怎么会“我抄我自己”?(当然NOIP2018“我抄我自己 ...

  4. BZOJ&period;1018&period;&lbrack;SHOI2008&rsqb;堵塞的交通&lpar;线段树维护连通性&rpar;

    题目链接 只有两行,可能的路径数不多,考虑用线段树维护各种路径的连通性. 每个节点记录luru(left_up->right_up),lurd,ldru,ldrd,luld,rurd,表示这个区 ...

  5. bzoj 3533&colon; &lbrack;Sdoi2014&rsqb;向量集 线段树维护凸包

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=3533 题解: 首先我们把这些向量都平移到原点.这样我们就发现: 对于每次询问所得到的an ...

  6. &lbrack;BZOJ1018&rsqb;&lbrack;SHOI2008&rsqb;堵塞的交通traffic 线段树维护连通性

    1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec  Memory Limit: 162 MB Submit: 3795  Solved: 1253 [Sub ...

  7. bzoj 1018 线段树维护连通性

    本题将一道LCT的题特殊化(支持加边和删边,询问图的连通性),将图变成了2×m的网格图,然后就神奇地可以用线段树来维护. 对于每个区间[l,r],维护其四个角落之间的连通性(仅仅通过[l,r]这段的边 ...

  8. BZOJ 1095&colon; &lbrack;ZJOI2007&rsqb;Hide 捉迷藏&lpar;线段树维护括号序列&rpar;

    这个嘛= =链剖貌似可行,不过好像代码长度很长,懒得打(其实是自己太弱了QAQ)百度了一下才知道有一种高大上的叫括号序列的东西= = 岛娘真是太厉害了,先丢链接:http://www.shuizilo ...

  9. bzoj3995&lbrack;SDOI2015&rsqb;道路修建

    http://www.lydsy.com/JudgeOnline/problem.php?id=3995 线段树维护连通性. 我们发现,对于一个区间[L,R],我们只需要知道(1,L),(2,L),( ...

随机推荐

  1. Hashtable,HashMap,Dictionary的区别

    Hashtable和HashMap的区别:1.Hashtable是基于Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现,c#中无HashMap2.Hashtable ...

  2. z-index 所遇问题

    document.getElementById('wx_share_img').style.cssText = "width:100%;height:100%;position:fixed; ...

  3. Kendo Web UI Grid里时间格式转换

    我和大家分享一下我的kendo的学习心得.如果不好的地方多多包含或者给我留言请看图 kendo里时间格式如图Oder Date列里的格式.但是我们想把时间转换成中国人习惯的格式.如Shipped Da ...

  4. php讲中文json数据编码

    <?php function show_jsonmsg($data){ if(is_array($data)){ $return = $data; }else{ $return = array( ...

  5. Python Faker的使用&lpar;1&rpar;:基础使用方法与函数速查,生成随机数据

    在软件需求.开发.测试过程中,有时候需要使用一些测试数据,针对这种情况,我们一般要么使用已有的系统数据,要么需要手动制造一些数据. 在手动制造数据的过程中,可能需要花费大量精力和工作量,现在好了,有一 ...

  6. 『Python』&lowbar;&lowbar;getattr&lowbar;&lowbar;&lpar;&rpar;特殊方法

    self的认识 & __getattr__()特殊方法 将字典调用方式改为通过属性查询的一个小class, class Dict(dict): def __init__(self, **kw) ...

  7. java访问权限表

    private(私有的) 默认的(什么都不写) protected(受保护的) public(公共的 ) 同一个类中 yes   yes yes   yes 同一个包中不同类之间 no yes yes ...

  8. datetime学习

    四.datetime类 (一).datetime类的数据构成 datetime类其实是可以看做是date类和time类的合体,其大部分的方法和属性都继承于这二个类,相关的操作方法请参阅,本文上面关于二 ...

  9. 《口算大作战 2》DLC&colon;算法真奇妙

    211614331 王诚荣 211614354 陈斌 --第一次结对作业 DLC DLC:三年级混合运算模块现已更新!现在您可以愉快的使用三年级题库啦.同时您必须拥有本体才能使用此DLC 单击此处查看 ...

  10. 揭秘QQ 安全password框的原理

    这篇文章也算是朝花夕拾.事实上非常早曾经就知道的原理,如今拿出来和大家交流分享一下. 故事总要有缘由.那么这个故事的缘由就是,当我曾经写了一个获取其他进程password框password的时候(前几 ...