2019 百度之星复赛 补题

A - Diversity HDU - 6725 (树形dp)

2019 百度之星复赛 补题_第1张图片

若两个区间有交,显然可以把两个区间的值,都取在区间交集的端点的其中一个,

若没有交集的话,[l1,r1]<[l2,r2]时,取到r1和l2,也在区间的端点

因此,[l,r]的数,只由两端点决定,二选一,树形dp

#include
using namespace std;
#define pb push_back 
typedef long long ll;
const int N=1e5+10;
int t,n,u,v;
vectorE[N];
ll dp[N][2],a[N][2];
void dfs(int u,int fa)
{
	for(int i=0;i

 

 

B - Transformation HDU - 6726 (数学/找规律)

2019 百度之星复赛 补题_第2张图片

赛后补题,

第一次操作,(a,b+(b-a))或(a+(a-b),b),要么前项加(a-b),要么后项加(b-a)

第二次操作,要么前项加2*(a-b),要么后项加2*(b-a)

第三次操作,要么前项加4*(a-b),要么后项加4*(b-a)

所以,c-a必须是a-b的倍数,d-b必须是a-b的倍数

特判a=b的情形,再讨论x=(c-a)/(a-b)和y=(d-b)/(a-b),显然答案唯一,与字典序无关

x和y非负且不能有交集,且x与y的并集构成二进制形如000001111111111的序列

#include
using namespace std;
typedef long long ll;
int t;
ll a,b,c,d,x,y;
bool ok(ll x)//判断x是否形如000111111 右起一段连续的1 
{
	x++;
	x-=x&-x;
	return x==0; 
}
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		//每次操作 必a+=k*(a-b) 或b+=k*(b-a) k为2的幂次且从1起不断*2 
		scanf("%lld%lld%lld%lld",&a,&b,&c,&d);//c-a=x*(a-b) d-b=y*(b-a) x和y二进制无交集 
		if(a==b)//c和d不会改变 
		{
			if(c==a&&d==b)printf("Yes\n\n");
			else puts("No");
			continue; 
		}
		if((c-a)%(a-b)||(d-b)%(b-a))
		{
			puts("No");
			continue;
		}
		x=(c-a)/(a-b);y=(d-b)/(b-a);
		if(x<0||y<0||(x&y)||!ok(x|y))
		{
			puts("No");
			continue;
		}
		puts("Yes");
		for(int i=0;(x>>i&1)|(y>>i&1);i++)
		{
			if(x>>i&1)putchar('B');
			else putchar('A');
		}
		puts("");
	}
	return 0;
}

C - Quasi Binary Search Tree HDU - 6727 (二叉树/构造)

2019 百度之星复赛 补题_第3张图片

赛中AC,纪念一下

对于一棵子树来讲,其值一定是连续的,

所以子树值一定会被分成三段,[l,x],x+1,[x+2,r]

op[u]=0代表这棵子树中值最小的值出现在左子树,

op[u]=1代表出现在右子树

op[u]=2代表出现在根,根的时候分左子和右子的数量来讨论

数量相等时,再分左子和右子的最小值哪个小来讨论

#include 
#include 
#include 
#include 
#include 
#define fi first
#define se second
#define pb push_back
using namespace std;
const int INF=0x3f3f3f3f;
typedef long long ll;
const int mod=1e9+7;
const int N=1e5+10;
int t,n;
int rt,mn[N],op[N],sz[N],res[N];
int ls[N],rs[N],in[N];
int bs[N];
void init()
{
	bs[1]=233;
	for(int i=2;ir)return;
	if(l==r)
	{
		res[u]=l;
		return;
	}
	if(op[u]==0)
	{
		res[u]=l+sz[ls[u]];
		dfs2(ls[u],l,l+sz[ls[u]]-1);
		dfs2(rs[u],l+sz[ls[u]]+1,r);
	}
	else if(op[u]==1)
	{
		res[u]=l+sz[rs[u]];
		dfs2(rs[u],l,l+sz[rs[u]]-1);
		dfs2(ls[u],l+sz[rs[u]]+1,r);
	}
	else 
	{
		if(l+sz[ls[u]]l+sz[rs[u]])
		{
			res[u]=l+sz[rs[u]];
			dfs2(rs[u],l,l+sz[rs[u]]-1);
			dfs2(ls[u],l+sz[rs[u]]+1,r);
		}
		else
		{
			res[u]=l+sz[ls[u]];
			if(mn[ls[u]]mn[rs[u]])
			{
				dfs2(rs[u],l,l+sz[rs[u]]-1);
				dfs2(ls[u],l+sz[rs[u]]+1,r);
			}
		}
	}
}
int main()
{
	init();
	mn[0]=INF;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;++i)
		in[i]=ls[i]=rs[i]=sz[i]=0,mn[i]=n+1;
		for(int i=1;i<=n;++i)
		{
			scanf("%d%d",&ls[i],&rs[i]);
			in[ls[i]]++,in[rs[i]]++;
		} 
		for(int i=1;i<=n;++i)
		{
			if(!in[i])
			{
				rt=i;
				break;
			}
		}
		dfs(rt);
		dfs2(rt,1,n);
		ll ans=0;
		for(int i=1;i<=n;++i)
		ans=(ans+(res[i]^i)*1ll*bs[i]%mod)%mod;
		printf("%lld\n",ans);
	}
	return 0;
}
/*
2
5
0 0
0 5
1 0
2 3
0 0
5
0 0
0 0
0 4
2 0
1 3
*/ 

 

你可能感兴趣的:(#,百度之星,#,树形dp/换根dp/长链剖分,思维题,百度之星,树形dp,二叉树,构造,找规律)