列表

详情


NC23862. Chino with Rewrite

描述

Chino的数学很差,因此Cocoa非常担心。这一天,Cocoa准备教Chino如何出题。
«Rewrite»是Key社的一款非常好玩的文字冒险游戏,在游戏的背景设定里,かがり需要完成一棵世界树的重构,重写这个世界。
这很像出题呢,一开始只有几个零星的idea,慢慢地把它们组织到一起,变成了一道完整的题目。
Cocoa告诉Chino应该按照如下的方式出题:
1、起初,平面上只有个知识点,每个知识点都有一个权值,接下来LoliconAutomaton准备通过次操作将它们连成一棵知识(我们姑且称作“智慧树”):
2、操作“1 x y”表示了直接连接x,y两个知识点,并把它们的权值更新为,如果x,y已经直接或者间接地连通,忽略本次操作。其中表示“x向下取整”,例如.
3、操作“2 x y”询问的唯一路径上的知识点有几种不同的权值,如果x,y当前尚未连通,请输出-1.
现在Cocoa希望Chino能够回答每一个“2 x y”.
题目对Chino来说太难啦,你能帮一帮Chino吗?

输入描述

第一行是两个正整数n, q;接下来一行是n个正整数Wi;接下来n-1行每行两个数u, v,描述了树上的一条边;接下来q行每行描述了一组询问

输出描述

对于每个2 x y,你应该作出回答

示例1

输入:

5 8
3 2 7 6 7
1 1 2
1 1 3
2 2 3
1 2 4
2 1 5
1 2 5
1 1 5
2 3 5

输出:

2
-1
2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 393ms, 内存消耗: 6248K, 提交时间: 2020-01-10 14:08:46

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
#define ls(x) t[x].ch[0]
#define rs(x) t[x].ch[1]
const int N=1e5+10;
int cnt,st[N],n,q;
struct node{
	int ch[2],fa,re,val,col;
}t[N];
inline void push_up(int p){
	t[p].val=t[ls(p)].val|t[rs(p)].val|(1LL<<t[p].col);
}
inline void push_re(int p){swap(ls(p),rs(p)); t[p].re^=1;}
inline void push_down(int p){
	if(!t[p].re)	return;
	if(ls(p))	push_re(ls(p));	if(rs(p))	push_re(rs(p)); t[p].re^=1;
}
inline bool isroot(int x){return ls(t[x].fa)!=x&&rs(t[x].fa)!=x;}
inline void rotate(int x){
	int y=t[x].fa,z=t[y].fa,k=rs(y)==x,w=t[x].ch[!k];
	if(!isroot(y))	t[z].ch[rs(z)==y]=x; t[x].ch[!k]=y; t[y].ch[k]=w;
	if(w)	t[w].fa=y; t[y].fa=x; t[x].fa=z;	push_up(y);
}
inline void splay(int x){
	cnt=1;	st[cnt]=x; int y=x;
	while(!isroot(y))	st[++cnt]=y=t[y].fa;
	while(cnt)	push_down(st[cnt--]);
	while(!isroot(x)){
		int y=t[x].fa,z=t[y].fa;
		if(!isroot(y))	rotate((ls(y)==x)^(ls(z)==y)?x:y); rotate(x);
	}push_up(x);
}
inline void access(int x){
	for(int y=0;x;x=t[y=x].fa) splay(x),rs(x)=y,push_up(x); 
}
inline void makeroot(int x){
	access(x); splay(x); push_re(x);
}
inline int find(int x){
	access(x); splay(x); while(ls(x)) push_down(x),x=ls(x); 
	splay(x);	return x;
}
inline void split(int x,int y){
	makeroot(x); access(y); splay(y);
}
inline void link(int x,int y){
	if(find(x)==find(y))	return ;
	int tc=t[x].col+t[y].col>>1;
	makeroot(x),t[x].fa=y,t[x].col=tc,makeroot(y),t[y].col=tc;
}
inline void cut(int x,int y){
	makeroot(x); 
	if(find(y)==x&&t[y].fa==x&&!ls(y)) t[y].fa=rs(x)=0,push_up(x);
}
inline int ask(int x,int y){
	if(find(x)!=find(y))	return -1;
	split(x,y);	int tc=t[y].val,res=0;
	for(;tc;tc-=tc&(-tc))	res++;
	return res;
}
signed main(){
	cin>>n>>q;
	for(int i=1;i<=n;i++)	cin>>t[i].col;
	for(int i=1,op,x,y;i<=q;i++){
		scanf("%lld %lld %lld",&op,&x,&y);
		if(op==1)	link(x,y);
		else	printf("%lld\n",ask(x,y));
	}
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 294ms, 内存消耗: 118648K, 提交时间: 2020-03-17 16:35:02

#include<bits/stdc++.h>
using namespace std;
const int MAX=3e5+10;
typedef long long ll;
struct lenka
{
	int op,x,y;
}a[MAX];
int p[MAX];
int f(int x)
{
	return p[x]==x?p[x]:p[x]=f(p[x]);
}
vector<int>e[MAX];
int w[MAX];
int nex[MAX][21];
int d[MAX];
int num[MAX][61];
void dfs(int k,int fa,int dep)
{
	d[k]=dep;
	nex[k][0]=fa;
	num[k][w[k]]++;
	for(int j=1;j<=60;j++)
	num[k][j]+=num[fa][j];
	for(int i=1;i<=20;i++)
	nex[k][i]=nex[nex[k][i-1]][i-1];
	for(int i=0;i<e[k].size();i++)
	{
		int nex=e[k][i];
		if(nex==fa) continue;
		dfs(nex,k,dep+1);
	}
}
int LCA(int x,int y)
{
	if(x==y) return x;
	if(d[x]>d[y]) swap(x,y);
	for(int i=20;i>=0;i--)
	{
		if(d[x]<d[y]&&d[nex[y][i]]>=d[x]) y=nex[y][i];
	}
	for(int i=20;i>=0;i--)
	{
		if(nex[x][i]!=nex[y][i])
		{
			x=nex[x][i];
			y=nex[y][i];
		}
	}
	if(x!=y) return nex[x][0];
	return x;
}
int ans[MAX];
int main()
{
	memset(ans,0,sizeof ans);
	memset(nex,0,sizeof nex);
	memset(d,0,sizeof d);
	memset(num,0,sizeof num);
	int n,q;
	cin>>n>>q;
	for(int i=1;i<=n;i++)
	scanf("%d",&w[i]);
	for(int i=1;i<=q;i++)
	scanf("%d%d%d",&a[i].op,&a[i].x,&a[i].y);
	for(int i=1;i<=n;i++)
	p[i]=i;
	for(int i=1;i<=q;i++)
	{
		int fx=f(p[a[i].x]);
		int fy=f(p[a[i].y]);
		if(a[i].op==1)
		{
			if(fx==fy) continue;
			w[a[i].x]=w[a[i].y]=(w[a[i].y]+w[a[i].x])/2;
			e[a[i].x].push_back(a[i].y);
			e[a[i].y].push_back(a[i].x);
			p[fx]=fy;
		}
		else
		{
			if(fx!=fy) ans[i]=-1;
		}
	}
	for(int i=1;i<=n;i++)
	if(p[i]==i) dfs(i,0,1);
	for(int i=1;i<=q;i++)
	{
		if(a[i].op==2)
		{
			if(ans[i]==-1)
			{
				puts("-1");
				continue;
			}
			int x=a[i].x,y=a[i].y;
			int lca=LCA(x,y);
			int tot=0;
			for(int j=1;j<=60;j++)
			{
				if(w[lca]==j) tot+=(num[x][j]+num[y][j]+1-2*num[lca][j]>0);
				else tot+=(num[x][j]+num[y][j]-2*num[lca][j]>0);
			 } 
			 printf("%d\n",tot);
		}
	}
	return 0;
}

上一题