[硫化铂]星际航道
Posted StaroForgin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[硫化铂]星际航道相关的知识,希望对你有一定的参考价值。
星际航道
题目概述
题解
这道题要强制在线求出网格图的最小生成树,看起来很难搞的样子。
如果离线下来的话是可以线段树分治的,但在线就不好弄了。
我们想想在线我们会如何进行边的替换。
如果我们的
w
w
w是小于这条边原来的
w
w
w,那是不是这条边就变得更优了。
如果这条边原来就在我们的生成树,那就保持不变嘛,如果不在,我们就看它是否能替换原树上的边。
显然,这条边在树上插上去后会形成一个环,此时我们减去环上的最长边肯定是最优的,所以我们替换掉的肯定是两端点在树上路径中的最长边。
我们将它维护出来与
w
w
w比大小即可,这东西用
L
C
T
LCT
LCT很好维护。
但如果我们的
w
w
w如果是变大的不就做不了了吗。
没关系,我们这是网格图,我们可以考虑将它转对偶图。
容易发现,我们将网格图的一个生成树去掉后,剩下的边恰好可以在对偶图上形成一个生成树。
这点也非常容易证明,对偶图上的任意一个环必定对应着网格图中两个集合没有联通,反之亦然。
所以我们最后得到的其实是 网格图 中的 最小生成树 + 对偶图 中的 最大生成树。
那么我们其实可以维护两棵树,当它变小时就在第一棵树上找到它是不是能替换边以及替换哪条边,当它变大时就在第二棵树上找边,然后再进行删边加边的操作。
这样,我们就做到
O
(
log
n
)
O\\left(\\log n\\right)
O(logn)维护单次操作了。
时间复杂度 O ( q log n ) O\\left(q\\log n\\right) O(qlogn)。
源码
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
#define MAXN 100005
#define MAXM 500005
#define MAXQ 200005
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
#define lson (rt<<1)
#define rson (rt<<1|1)
const int INF=0x3f3f3f3f;
template<typename _T>
void read(_T &x)
_T f=1;x=0;char s=getchar();
while(s<'0'||s>'9')if(s=='-')f=-1;s=getchar();
while('0'<=s&&s<='9')x=(x<<3)+(x<<1)+(s^48);s=getchar();
x*=f;
template<typename _T>
void print(_T x)if(x>9)print(x/10);putchar(x%10+'0');
template<typename _T>
_T Fabs(_T x)return x<0?-x:x;
int add(int x,int y,int p)return x+y<p?x+y:x+y-p;
void Add(int &x,int y,int p)x=add(x,y,p);
int qkpow(int a,int s,int p)int t=1;while(s)if(s&1)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1;return t;
struct edgeint u1,v1,u2,v2,w,col;s[MAXM];
struct mingint ch[2],fa,maxx,mxid,minn,mnid,val,id;bool rev;;
int typ,R,C,q,n1,n2,m,id[MAXN][2];
class LinkCutTree
private:
ming tr[MAXM];int sta[MAXM],stak,nn;
void pushup(int rt)
tr[rt].maxx=(rt<=nn?-1:tr[rt].val),tr[rt].mxid=tr[rt].id;
tr[rt].minn=(rt<=nn?INF:tr[rt].val),tr[rt].mnid=tr[rt].id;
if(tr[rt].ch[0]&&tr[tr[rt].ch[0]].maxx>tr[rt].maxx)
tr[rt].maxx=tr[tr[rt].ch[0]].maxx,tr[rt].mxid=tr[tr[rt].ch[0]].mxid;
if(tr[rt].ch[0]&&tr[tr[rt].ch[0]].minn<tr[rt].minn)
tr[rt].minn=tr[tr[rt].ch[0]].minn,tr[rt].mnid=tr[tr[rt].ch[0]].mnid;
if(tr[rt].ch[1]&&tr[tr[rt].ch[1]].maxx>tr[rt].maxx)
tr[rt].maxx=tr[tr[rt].ch[1]].maxx,tr[rt].mxid=tr[tr[rt].ch[1]].mxid;
if(tr[rt].ch[1]&&tr[tr[rt].ch[1]].minn<tr[rt].minn)
tr[rt].minn=tr[tr[rt].ch[1]].minn,tr[rt].mnid=tr[tr[rt].ch[1]].mnid;
void Reverse(int rt)swap(tr[rt].ch[0],tr[rt].ch[1]);tr[rt].rev^=1;
void pushdown(int rt)
if(tr[rt].rev)
if(tr[rt].ch[0])Reverse(tr[rt].ch[0]);
if(tr[rt].ch[1])Reverse(tr[rt].ch[1]);
tr[rt].rev=0;
bool identify(int x)return tr[tr[x].fa].ch[1]==x;
bool isRoot(int x)return (tr[tr[x].fa].ch[0]^x)&&(tr[tr[x].fa].ch[1]^x);
void link(int x,int y,int d)tr[x].fa=y;tr[y].ch[d]=x;
void rotate(int x)
int y=tr[x].fa,z=tr[y].fa,d1=identify(x),d2=identify(y);
if(isRoot(y))tr[x].fa=z;else link(x,z,d2);int t=tr[x].ch[d1^1];
link(t,y,d1);link(y,x,d1^1);pushup(y);pushup(x);
void splay(int x)
int y=sta[stak=1]=x;while(!isRoot(y))sta[++stak]=y=tr[y].fa;
while(stak)pushdown(sta[stak--]);
for(y=tr[x].fa;!isRoot(x);rotate(x),y=tr[x].fa)
if(!isRoot(y))rotate(identify(x)==identify(y)?y:x);
void access(int x)for(int y=0;x;x=tr[y=x].fa)splay(x),tr[x].ch[1]=y,pushup(x);
void makeRoot(int x)access(x);splay(x);Reverse(x);
int findRoot(int x)
access(x);splay(x);pushdown(x);
while(tr[x].ch[0])pushdown(x=tr[x].ch[0]);
splay(x);return x;
public:
bool queryLink(int u,int v)makeRoot(u);return findRoot(v)==u;
int splitMax(int x,int y)makeRoot(x);access(y);splay(y);return tr[y].mxid;
int splitMin(int x,int y)makeRoot(x);access(y);splay(y);return tr[y].mnid;
void linkTree(int u,int v)makeRoot(u);if(findRoot(v)^u)tr[u].fa=v;
void cutTree(int u,int v)if(!queryLink(u,v))return ;tr[v].fa=tr[u].ch[0]=0;pushup(u);
void modify(int x,int w)tr[x].maxx=tr[x].minn=tr[x].val=w;
void init(int x)
for(int i=1;i<=m;i++)tr[i+x].mxid=tr[i+x].mnid=tr[i+x].id=i;
for(int i=1;i<=x;i++)tr[i].maxx=-1,tr[i].minn=INF;
nn=x;
T1,T2;
int Id1(int x,int y)return (x-1)*C+y;
int Id2(int x,int y)
if(x<1||y<1||x>=R||y>=C)return (R-1)*(C-1)+1;
return (x-1)*(C-1)+y;
int fa[MAXN];
void makeSet(int x)for(int i=1;i<=x;i++)fa[i]=i;
int findSet(int x)return fa[x]==x?x:fa[x]=findSet(fa[x]);
void unionSet(int a,int b)int u=findSet(a),v=findSet(b);if(u^v)fa[u]=v;
inline void decode(char ch,int &x,int &y,int &w,LL lstans)
static int mask=0xfffff;
w=(int)以上是关于[硫化铂]星际航道的主要内容,如果未能解决你的问题,请参考以下文章