zl程序教程

您现在的位置是:首页 >  云平台

当前栏目

实时查询(otoci)

实时 查询
2023-09-27 14:28:32 时间

暂无链接

实时查询

[问题描述]

给出n个结点以及每个结点对应的权值起始时,结点与结点之间没有连边
有以下三类操作:

(1) bridge A B:询问结点A与结点B是否连通,如果是,则输出“no”;否则,输出
“yes”,并且在结点A和结点B之间连一条无向边:

(2) penguins A X:将结点A对应的权值 W A W_A WA修改为X

(3) excursion A B如果结点A和结点B不连通,则输出“impossible”;否则,输出结点 A到结点B的路径上的点对应的权值的和。

给出q个操作,要求处理所有操作。

[输入格式]

第一行包含一个整数 n ( 1 ≤ n ≤ 30000 ) n(1\le n\le 30000) n(1n30000).表示结点的数B。

第二行包含n个整数.第i个整数表示第i个结点初始时对应的权值。

第三行包含一个整数 q ( 1 ≤ q ≤ 300000 ) q(1\le q \le 300000) q(1q300000)表示操作的数目

以下q行.每行包含一个操作,操作的类别见题目描述。

任意时刻每个结点对应的权值都足1到1000之间的整数。

[输出格式]

输出所有bridge操作和excursion操作对应的输出,每个一行。

[输入样例]

6
1 2 3 4 5 6
10
bridge 1 2
bridge 2 3
bridge 4 5
excursion 1 3
excursion 1 5
bridge 3 4
excursion 1 5
penguins 3 10
excursion 1 3
bridge 1 5

[输出样例]

yes
yes
yes
6
impossible
yes
15
13
no

[时间和空间限制]

时间限制为1秒,空间限制为256MB。

题解

也是很板的 L C T \mathcal{LCT} LCT了,只需要维护一个点权和就好了。

判断连通性可以用并查集,因为没有删边的操作,能不用 f i n d r o o t findroot findroot就不用。

但是 L C T \mathcal{LCT} LCT依然很慢,要加常数优化才能A最后一个点。

代码
#include<bits/stdc++.h>
#define R register int
#define I inline void
#define ls son[v][0]
#define rs son[v][1]
using namespace std;
const int M=3e4+5;
int son[M][2],dad[M],sum[M],sta[M],val[M],f[M],n,q;
bool rev[M];
inline bool notroot(int v){return son[dad[v]][0]==v||son[dad[v]][1]==v;}
I up(R v){sum[v]=val[v]+sum[ls]+sum[rs];}
I turn(R v){swap(ls,rs);rev[v]^=1;}
I push(R v){if(!rev[v])return;if(ls)turn(ls);if(rs)turn(rs);rev[v]=0;}
I spin(R v)
{
	int f=dad[v],ff=dad[f],k=son[f][1]==v,w=son[v][!k];
	if(notroot(f))son[ff][son[ff][1]==f]=v;
	son[v][!k]=f;son[f][k]=w;
	if(w)dad[w]=f;
	dad[f]=v;dad[v]=ff;
	up(f);up(v);
}
I splay(R v)
{
	int f,ff,top=0,u=v;
	sta[++top]=u;
	while(notroot(u))sta[++top]=u=dad[u];
	while(top)push(sta[top--]);
	while(notroot(v))
	{
		f=dad[v];ff=dad[f];
		if(notroot(f))spin((son[f][0]==v)^(son[ff][0]==f)?v:f);
		spin(v);
	}
}
I access(R v){for(R f=0;v;v=dad[f=v])splay(v),rs=f,up(v);}
I beroot(R v){access(v);splay(v);turn(v);}
I split(R x,R y){beroot(x);access(y);splay(y);}
I link(R x,R y){beroot(x);dad[x]=y;}
int find(R v){return f[v]==v?v:f[v]=find(f[v]);}
void in()
{
	scanf("%d",&n);
	for(R i=1;i<=n;++i)
	scanf("%d",&val[i]),sum[i]=val[i],f[i]=i;
}
void ac()
{
	int a,b,t1,t2;
	char ch[20];
	scanf("%d",&q);
	for(R i=1;i<=q;++i)
	{
		scanf("%s%d%d",ch,&a,&b);
		switch(ch[0])
		{
			case 'b':{
				t1=find(a);t2=find(b);
				if(t1==t2){printf("no\n");break;}
				printf("yes\n");link(a,b);f[t1]=t2;
				break;
			}
			case 'p':splay(a);val[a]=b;up(a);break;
			case 'e':{
				t1=find(a);t2=find(b);
				if(t1!=t2){printf("impossible\n");break;}
				split(a,b);printf("%d\n",sum[b]);
				break;
			}
		}
	}
}
int main()
{
	in();ac();
	return 0;
}