字节跳动冬令营2018

链接:https://ac.nowcoder.com/acm/contest/296

C

给定一棵有根树,边有边权,两个人轮流操作,每次可以把一条边的权值减少一,权值变为 0 表示把子树砍掉,问先手第一轮操作哪些边使得自己必胜。 n ≤ 1 0 6 n\leq 10^6 n106

之前的博客,发现这道题本质上是图的删边游戏。把环缩掉,就变成了树上删边游戏了。结论是:叶子的 sg 为 0,非叶子的 sg 为所有叶子的 sg+1 的异或。求方案就是求删掉哪些边使得根的 sg 为 0。dfs 一遍即可。

E

有 n 个集合成一个环,每个集合大小为 m,要求 ∣ S i − S j ∣ ≥ l i |S_i-S_j|\geq l_i SiSjli,要求最小化 ∣ ⋃ S i ∣ |\bigcup S_i| Si

首先,如果是一排,答案就是 max ⁡ ( m + l i ) \max (m+l_i) max(m+li)
如果是一个环,就要让最后一个集合和第一个集合的差尽可能大。我们二分一个答案,然后尝试 DP 这个东西。设 f i , j , 0 / 1 f_{i,j,0/1} fi,j,0/1 表示第 i 个集合与第一个集合的交 最多/最少 是多少。如果我们想让 i 的交最多,那么 i-1 的交一定要尽量少,反之亦然。

#include<bits/stdc++.h>
#define ll long long
#define db double
using namespace std;
const int N=1000010;
ll f[N][2],l[N];int n;
int read()
{
	int x=0,flag=1;char c=getchar();
	while(!isdigit(c)) {if(c=='-') flag=-1;c=getchar();}
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x*flag;
}
bool check(ll lim,ll m)
{
	f[0][0]=f[0][1]=m;
	ll A=m,B=lim-m;
	for(int i=1;i<n;i++)
	{
		ll ss=f[i-1][0],tt=m-ss;
		if(A-ss>=l[i]) f[i][1]=m;
		else f[i][1]=m-(l[i]-(A-ss));
		
		ss=f[i-1][1],tt=m-ss;
		if(B-tt>=l[i]) f[i][0]=0;
		else f[i][0]=l[i]-(B-tt);
	}
	return m-f[n-1][0]>=l[0];
}
int main()
{
	int T=read();
	while(T--)
	{
		n=read(); ll m,mx=0; cin>>m;
		for(int i=0;i<n;i++) cin>>l[i],mx=max(mx,l[i]);
		if(mx>m) {cout<<-1<<'\n';continue;}
		ll l=m,r=m+2*mx,ans=-1;
		while(l<=r)
		{
			ll mid=l+r>>1;
			if(check(mid,m)) r=mid-1,ans=mid;
			else l=mid+1;
		}
		assert(ans!=-1);
		cout<<ans<<'\n';
	}
	return 0;
}

G

有一个由 w 组成的无限长度的字符串 w w r w w r . . . ww^rww^r... wwrwwr... w r w^r wr 表示把 w 翻转。从这个无限长的字符串里截一个子串 s(长度严格大于 w),满足 s 包含 w 或者 w 的反串作为子串。现在给出 s,求有多少子区间满足这个区间的字符串可能是 w。字符串长度小于等于1e6。

H

n 个点 m 条边的无向图,有 k 个加速点。你一开始速度为 1,经过一个加速点速度会乘2。可以经过一个点/边 多次,注意连续经过的两个加速点不能是同一个。求从 1 到 n 的最短时间。 k ≤ n ≤ 100 , m ≤ 8000 k\leq n\leq 100,m\leq 8000 kn100,m8000

f i , j f_{i,j} fi,j 表示从 1 到 i 经过 j 个加速点的最短时间,枚举经过的最后一个加速点是什么,预处理两点最短路即可转移。

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值