列表

详情


NC21820. 筱玛的D球

描述

筱玛是一个快乐的D球主席。
在筱玛的D球上,有n个国家由n-1条边连接,每个国家都可以到达其他所有国家。
每个国家拥有一个D人手段oi,每条道路由一个D人值wi
由于某些不为人知的原因,筱玛钦点D人手段只能为以下三种:
  • xor
  • or
  • and
每次,筱玛会钦点一条路径。假设经过的点是v0,v1,...,vn,经过的边为e1,e2,...,en,并给出两个D人参数x和y。
你需要给出一个最小的s,使得s≤ x,且最大。
注意这里的运算顺序为从左往右
由于筱玛太快乐了,他还会修改一条边或一个点的权值。

输入描述

第一行两个整数n,m分别表示边数和点数。
接下来n-1每行两个整数u,v代表一条边。
接下来m行,每行若干个整数,描述一个操作。
每个操作的格式如下:opt [args]
● 当opt=1时,表示询问操作,[args]为"u v x y",表示询问的路径是u-v,x,y见题面描述。
● 当opt=2时,表示点修改,[args]为"i str",表示修改的点为i,将这个点的运算符改为str。
● 当opt=3时,表示边修改,[args]为"i v",表示修改的边为i,将其权值改为v。

输出描述

对于每一个opt=1的操作,输出一行一个整数,表示你选择的s。

示例1

输入:

3 3
1 2
1 3
1 2 3 3135152414104478727 17505530317743439490
1 3 3 3210377389414950277 3108503171776756205
1 2 2 1294554283713988838 16470947796150090874

输出:

941213755966112125
1503182846650631698
1255220337180181381

说明:

这组数据中,所有的节点都是{\rm or},所有的边权都是0,所以相当于查询最小的\le x的数使得其{\rm or}\ y的结果最大。
第一个询问解释如下:
(941213755966112125)_{10}=(0000110100001111110111001110110010011110000100100100000101111101)_2
(17505530317743439490)_{10}=(1111001011110000001000110001001101100001111011011011111010000010)_2
结果为最大值,(1111111111111111111111111111111111111111111111111111111111111111)_2

原站题解

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

C++11(clang++ 3.9) 解法, 执行用时: 2083ms, 内存消耗: 120280K, 提交时间: 2020-03-26 11:15:45

#include<iostream>
#include<cstdio>
#define ul unsigned long long
using namespace std;
int n,m,top,st[1001010];
int fa[1001010],s[1001011][2],rev[1001010];
char S[10];
struct ev
{
	ul f0,f1,val;
	int opt;
	ev operator + (const ev &b)const
	{
		ev res;
		res.f0=(~f0&b.f0)|(f0&b.f1);
		res.f1=(~f1&b.f0)|(f1&b.f1);
		res.val=val;
		res.opt=opt;
		return res;
	}
}v[1001010],anl[1001010],anr[1001010];
bool isrot(int x)
{
	return s[fa[x]][0]==x||s[fa[x]][1]==x;
}
void rv(int x)
{
	swap(s[x][0],s[x][1]);
	swap(anl[x],anr[x]);
	rev[x]^=1;
}
ev cg(ul vv,int op)
{
	if(op==1) return (ev){0,vv};
	if(op==2) return (ev){vv,0xffffffffffffffff};
	return (ev){vv,~vv};
}
void pushup(int x)
{
	int l=s[x][0],r=s[x][1];
	anl[x]=anr[x]=v[x];
	if(l)
	{
		if(!v[x].opt) anl[x]=cg(v[x].val,anr[l].opt)+anl[x];
		else anr[x]=anr[x]+cg(anr[l].val,v[x].opt);
		anl[x]=anl[l]+anl[x];
		anr[x]=anr[x]+anr[l]; 
	}
	if(r)
	{
		if(!v[x].opt) anr[x]=cg(v[x].val,anl[r].opt)+anr[x];
		else anl[x]=anl[x]+cg(anl[r].val,v[x].opt);
		anl[x]=anl[x]+anl[r];
		anr[x]=anr[r]+anr[x];
	}
}
void pushdown(int x)
{
	if(rev[x])
	{
		if(s[x][0]) rv(s[x][0]);
		if(s[x][1]) rv(s[x][1]);
		rev[x]=0;
	}
}
void rot(int x)
{
	int y=fa[x],z=fa[y],d=s[y][1]==x;
	if(isrot(y))
	s[z][s[z][1]==y]=x;
	fa[x]=z;
	fa[y]=x;
	if(s[x][!d])
	fa[s[x][!d]]=y;
	s[y][d]=s[x][!d];
	s[x][!d]=y;
	pushup(y);
}
void splay(int x)
{
	st[top=1]=x;
	for(int i=x;isrot(i);i=fa[i])
	st[++top]=fa[i];
	while(top)
	pushdown(st[top--]);
	while(isrot(x))
	{
		int y=fa[x],z=fa[y];
		if(isrot(y))
		(s[z][1]==y)^(s[y][1]==x)?rot(x):rot(y);
		rot(x); 
	}
	pushup(x);
}
void access(int x)
{
	for(int y=0;x;x=fa[y=x]) splay(x),s[x][1]=y,pushup(x);
}
void makeroot(int x)
{
	access(x);
	splay(x);
	rv(x);
}
void split(int x,int y)
{
	makeroot(x);
	access(y);
	splay(y);
}
void link(int x,int y,int z)
{
	makeroot(x);
	fa[x]=z;
	fa[z]=y;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	v[i].opt=2,v[i].f0=0,v[i].f1=0xffffffffffffffff,v[i].val=0;
	for(int i=n+1,x,y;i<=n+n-1;i++)
	{
		scanf("%d%d",&x,&y);
		link(x,y,i);
		v[i].opt=0;
		v[i].f0=0;
		v[i].f1=0xffffffffffffffff;
		v[i].val=0;
	}
	for(int i=1,t,x,y;i<=m;i++)
	{
		scanf("%d",&t);
		if(t==1)
		{
			ul z,k;
			scanf("%d%d%llu%llu",&x,&y,&z,&k);
			split(x,y);
			ev a1=anl[y]+cg(k,anr[y].opt);
			ul aa=a1.f0,bb=a1.f1,ans=0,t=1;
			for(int j=63;~j;j--)
			if((aa&(t<<j))==0&&(bb&(t<<j))&&(t<<j)<=z)
			ans+=(t<<j),z-=(t<<j);
			printf("%llu\n",ans); 
		}
		else if(t==2)
		{
			scanf("%d%s",&x,S);
			makeroot(x);
			if(S[0]=='a') v[x].opt=1;
			if(S[0]=='o') v[x].opt=2;
			if(S[0]=='x') v[x].opt=3;
			pushup(x);
		}
		else if(t==3)
		{
			ul z;
			scanf("%d%llu",&x,&z);
			makeroot(x+n);
			v[x+n].val=z;
			pushup(x+n);
		}
	}
	return 0;
}

上一题