【题解】Luogu P5360 [SDOI2019]世界地图
原题传送门
每次查询的实际就是将地图的一个前缀和一个后缀合并后的图的最小生成树边权和
我们要预处理每个前缀和后缀的最小生成树
实际求前缀和(后缀和)的过程珂以理解为上一个前缀和这一列的最小生成树进行合并,实际最后前缀和后缀合并也是这样
如果暴力进行合并的话,每次边数是nm级别的,明显会TLE和MLE
我们考虑一下,实际每次合并主要和最左、最右两列(称这些点为关键点)有关,每次合并,原来最小生树中有可能会有一些边要删掉使得合并后是最小生成树。感性理解一下,珂能删掉的边一定在两个关键点在原来最小生成树之间的链上,所以我们对关键点建最小生成树的虚树,边权为原来最小生成树之间两点边权的最大值,其他的边权累加成和即可(因为其他的边不珂能删掉),这时两个最小生成树的边数的数量级都是n*常数的,所以直接暴力kruscal。
这个算法的复杂度大概为\(O(n*(m+q)\log n)\)
#include <bits/stdc++.h>
#define N 10005
#define ll long long
using namespace std;
inline int read()
{
    register int x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*f;
}
inline void write(register ll x)
{
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[20];register int tot=0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
inline int Max(register int a,register int b)
{
    return a>b?a:b;
}
int n,m,q,foo[N][105],bar[N][105];
unsigned int SA,SB,SC;
int lim;
inline int rng()
{
    SA^=SA<<16;SA^=SA>>5;SA^=SA<<1;
    unsigned int t=SA;SA=SB;SB=SC;SC^=t^SA;
    return SC%lim+1;
}
struct edge{
    int u,v,w;
    bool operator < (const edge &b)const{return w<b.w;}
};
struct MST{
    int tot;
    ll sum;
    vector <edge> E;
    MST(){}
    MST(register int *c)
    {
        tot=n,sum=0;
        for(register int i=1;i<n;++i)
            E.push_back((edge){i,i+1,c[i]});
    }
    inline ll query()
    {
        ll res=sum;
        for(register int i=0;i<E.size();++i)
            res+=E[i].w;
        return res;
    }
}pre[N],suf[N];
int tot,fa[N],mrk[N],to[N],nxt[N],ww[N],head[N],cnt;
vector <edge> E;
ll ans;
inline int find(register int x)
{
    return x==fa[x]?x:fa[x]=find(fa[x]);
}
inline void link(register edge x)
{
    to[++cnt]=x.v,nxt[cnt]=head[x.u],ww[cnt]=x.w,head[x.u]=cnt;
    to[++cnt]=x.u,nxt[cnt]=head[x.v],ww[cnt]=x.w,head[x.v]=cnt;
    ans+=x.w;
}
inline bool dfs1(register int u,register int f)
{
    int s=0;
    for(register int e=head[u];e;e=nxt[e])
        if(to[e]!=f)
            s+=dfs1(to[e],u);
    mrk[u]|=(s>=2);
    s+=mrk[u];
    return s;
}
inline void dfs2(register int u,register int f,register int lst,register int val)
{
    if(mrk[u])
    {
        if(lst)
            E.push_back((edge){mrk[u],lst,val});
        lst=mrk[u];
        ans-=val;
        val=0;
    }
    for(register int e=head[u];e;e=nxt[e])
        if(to[e]!=f)
            dfs2(to[e],u,lst,Max(val,ww[e]));
}
inline MST merge(register MST a,register MST b,register int *c)
{
    tot=a.tot+b.tot;
    E.clear();
    for(register int i=0;i<a.E.size();++i)
        E.push_back(a.E[i]);
    for(register int i=0;i<b.E.size();++i)
        E.push_back((edge){b.E[i].u+a.tot,b.E[i].v+a.tot,b.E[i].w});
    for(register int i=1;i<=n;++i)
        E.push_back((edge){a.tot-n+i,a.tot+i,c[i]});
    sort(E.begin(),E.end());
    for(register int i=1;i<=tot;++i)
        fa[i]=i,mrk[i]=(i<=n||i>tot-n),head[i]=0;
    cnt=ans=0;
    for(register int i=0;i<E.size();++i)
    {
        edge x=E[i];
        if(find(x.u)!=find(x.v))
            link(x),fa[find(x.u)]=find(x.v);
    }
    dfs1(1,0);
    cnt=0;
    for(register int i=1;i<=tot;++i)
        if(mrk[i])
            mrk[i]=++cnt;
    E.clear();
    dfs2(1,0,0,0);
    MST res;
    res.tot=cnt;
    res.sum=a.sum+b.sum+ans;
    res.E=E;
    return res;
}
int main()
{
    n=read(),m=read();
    scanf("%u%u%u",&SA,&SB,&SC);
    lim=read();
    for(register int i=1;i<=n;++i)
        for(register int j=1;j<=m;++j)
            foo[j][i]=rng();
    for(register int i=1;i<n;++i)
        for(register int j=1;j<=m;++j)
            bar[j][i]=rng();
    pre[1]=MST(bar[1]),suf[m]=MST(bar[m]);
    for(register int i=2;i<m;++i)
        pre[i]=merge(pre[i-1],MST(bar[i]),foo[i-1]);
    for(register int i=m-1;i>1;--i)
        suf[i]=merge(MST(bar[i]),suf[i+1],foo[i]);
    q=read();
    while(q--)
    {
        int l=read(),r=read();
        write(merge(suf[r+1],pre[l-1],foo[m]).query()),puts("");
    }
    return 0;
}
【题解】Luogu P5360 [SDOI2019]世界地图的更多相关文章
- [题解] Luogu P5446 [THUPC2018]绿绿和串串
		[题解] Luogu P5446 [THUPC2018]绿绿和串串 ·题目大意 定义一个翻转操作\(f(S_n)\),表示对于一个字符串\(S_n\), 有\(f(S)= \{S_1,S_2,..., ... 
- 【题解】Luogu P5358 [SDOI2019]快速查询
		原题传送门 神鱼说这道题是强制离线(smog 我们珂以把被单点修改,单点查询的点单独拿出来处理,把每个数表示成\(mul*x+plus\) 初始状态下\(mul=1,plus=0\) 操作1:在总和中 ... 
- 【题解】Luogu P5361 [SDOI2019]热闹又尴尬的聚会
		原题传送门 构造题. 明显p,q都越大越好 我们考虑每次取出度最小的点,加到尴尬聚会的集合中(因为把与它相邻的点全删了,不珂能出现认识的情况),把它自己和与自己相连的点从图上删掉(边也删掉),记下这个 ... 
- 题解 Luogu P2499: [SDOI2012]象棋
		关于这道题, 我们可以发现移动顺序不会改变答案, 具体来说, 我们有以下引理成立: 对于一个移动过程中的任意一个移动, 若其到达的位置上有一个棋子, 则该方案要么不能将所有棋子移动到最终位置, 要么可 ... 
- 题解 luogu P1144 【最短路计数】
		本蒟蒻也来发一次题解第一篇请见谅 这个题有几个要点 1.无向无权图,建图的时候别忘记建来回的有向边[因此WA掉1次 2.无权嘛,那么边长建成1就好了2333333 3.最短路采用迪杰斯特拉(别忘用堆优 ... 
- 题解 Luogu P1110 【[ZJOI2007]报表统计】
		感谢 @cmy962085349 提供的hack数据,已经改对了. 先声明,我好像是题解里写双$fhq$ $treap$里唯一能过的...(最后两个点啊) 思路:首先看题目,$MIN_GAP_SORT ... 
- [VIJOS2053][SDOI2019]世界地图:最小生成树+虚树
		分析 可以发现第一列和最后一列永远不会被删除,于是我们可以想到维护前后缀最小生成树,但是直接维护的话显然时间空间两爆炸.(通过上网找题解)可以发现我们关心的只是最左边和最右边两列,而不关心内部的连边情 ... 
- 题解 Luogu P3370
		讲讲这题的几种做法: 暴力匹配法 rt,暴力匹配,即把字符串存起来一位一位判相等 时间复杂度$ O(n^2·m) $ 再看看数据范围 \(n\le10^5,m\le10^3\) 当场爆炸.当然有暴力分 ... 
- 题解 Luogu P3623 [APIO2008]免费道路
		[APIO2008]免费道路 题目描述 新亚(New Asia)王国有 N 个村庄,由 M 条道路连接.其中一些道路是鹅卵石路,而其它道路是水泥路.保持道路免费运行需要一大笔费用,并且看上去 王国不可 ... 
随机推荐
- 洛谷 P5614题解
			吐槽:数据好像有点水,直接枚举到200可以得80 points. 另:我还是太弱了,比赛的时候只有90 points,#7死卡不过去,最后发现是没有判断 \(z_1\) 和 \(z_2\) 的范围-- ... 
- JDBC PreparedStatement Statement
			参考:预编译语句(Prepared Statements)介绍,以MySQL为例 1. 背景 本文重点讲述MySQL中的预编译语句并从MySQL的Connector/J源码出发讲述其在Java语言中相 ... 
- maven 左边空了
			看一下maven: 解决方法:进入maven的配置,把maven的路径配置一下,就好了: 结果: 
- 【Gamma】Scrum Meeting 4
			目录 写在前面 进度情况 任务进度表 Gamma阶段燃尽图 照片 写在前面 例会时间:5.31 22:30-23:00 例会地点:微信群语音通话 代码进度记录github在这里 临近期末,团队成员课程 ... 
- CT窗宽位宽
			先说一下CT值是什么 CT图像反映的是人体对X射线吸收的系数,但我们关心的是各组织结构的密度差异,即相对密度,如果某组织发生病变,其密度就会发生变化,但由于比较吸收系数非常繁琐,于是亨氏把组织器官对X ... 
- Navicat 12.x for MySQL最新版安装破解教程(附安装包和注册机,全网独家可用
			title: "Navicat 12.x for MySQL最新版安装破解教程(附安装包和注册机,全网独家可用" categories: soft tags: soft autho ... 
- C# Area区域配置,修改默认路由
			1.右键项目新建文件夹 Areas 2.先把项目分类包好,建两个文件夹,放Controller和View,Model也可以放在这里 因为项目启动默认打开的是Home/Index ,我把它放在了Webs ... 
- Django入门2开发工具pycharm的配置
			在pycharm中新建django项目 查看django是否安装成功 运行django 设置pycharm快捷键 设置python模板,新建的python文件就会自动生成一些信息 设置django启动 ... 
- PHP 指定时间/时间戳+某天/某月/某年
			PHP指定时间戳加上1天,1周,1月,一年其实是不需要用上什么函数的!指定时间戳本身就是数字整型,我们只需要再计算1天,1周它的秒数相加即可! 博主搜索php指定时间戳加一天一年,结果许多的文章给出来 ... 
- 在网址前加神秘字母,让你打开新世界(z)
			在网址前加神秘字母,让你打开新世界 1.在百度云后面加“wp”可以高速下载百度云资源<ignore_js_op> 2.在任何网址前面加“wn.run”(一定要加到这个网址www的前面)之后 ... 
