Ethflow Round 1 (Codeforces Round 1001, Div. 1 + Div. 2)(A~E1)题解记录

好久没写codeforces题解,这次E1赛后才做出来,为了方便点,先不把题目挂出来了
比赛链接:https://codeforces.com/contest/2062

A.String

思路:显然可以发现,选择方法形如10101,这种其实是最佳的,然后可以发现这种变成全0的次数等于其1的个数,故归纳一下,本题答案就是对应字符串1的个数

	#include<iostream>
	#include<queue>
	#include<map>
	#include<set>
	#include<vector>
	#include<algorithm>
	#include<deque>
	#include<cctype>
	#include<string.h>
	#include<math.h>
	#include<time.h>
	#include<random>
	#include<functional>
	#include<stack>
	#include<string>
	#define ll                                  long long 
	#define lowbit(x) (x & -x)
	#define endl "\n"//                           交互题记得删除
	using namespace std;
	mt19937 rnd(time(0));
	const ll mod = 998244353;
	//const ll p=rnd()%mod;
	ll ksm(ll x, ll y)
	{
		ll ans = 1;
		while (y)
		{
			if (y & 1)
			{
				ans = ans % mod * (x % mod) % mod;
			}
			x = x % mod * (x % mod) % mod;
			y >>= 1;
		}
		return ans % mod % mod;
	}
	ll gcd(ll x, ll y)
	{
		if (y == 0)
			return x;
		else
			return gcd(y, x % y);
	}
	void fio()
	{
		ios::sync_with_stdio(0);
		cin.tie(0);
		cout.tie(0);
	}
	struct s
	{
		ll l,r;
		bool operator<(const s&a)
		{
		}
	};
	int main()
	{
		fio();
		ll t;
		cin>>t;
		while(t--)
		{
			string f;
			cin>>f;
			ll cnt=0;
			for(ll i=0;i<f.size();i++)
			{
				cnt+=(f[i]=='1');
			}
			cout<<cnt<<endl;
		}
	}

B.Clockwork

思路:考虑最坏情况即可,即从一个点出发,从该点出发前往最远端回来,如果回来之前变为0,则一定无解。如果都满足,显然移动周期内都可以过所有点一遍的

	#include<iostream>
	#include<queue>
	#include<map>
	#include<set>
	#include<vector>
	#include<algorithm>
	#include<deque>
	#include<cctype>
	#include<string.h>
	#include<math.h>
	#include<time.h>
	#include<random>
	#include<functional>
	#include<stack>
	#include<string>
	#define ll                                  long long 
	#define lowbit(x) (x & -x)
	#define endl "\n"//                           交互题记得删除
	using namespace std;
	mt19937 rnd(time(0));
	const ll mod = 998244353;
	//const ll p=rnd()%mod;
	ll ksm(ll x, ll y)
	{
		ll ans = 1;
		while (y)
		{
			if (y & 1)
			{
				ans = ans % mod * (x % mod) % mod;
			}
			x = x % mod * (x % mod) % mod;
			y >>= 1;
		}
		return ans % mod % mod;
	}
	ll gcd(ll x, ll y)
	{
		if (y == 0)
			return x;
		else
			return gcd(y, x % y);
	}
	void fio()
	{
		ios::sync_with_stdio(0);
		cin.tie(0);
		cout.tie(0);
	}
	struct s
	{
		ll l,r;
		bool operator<(const s&a)
		{
		}
	};
	ll a[5450000];
	int main()
	{
		fio();
		ll t;
		cin>>t;
		while(t--)
		{
			ll n;
			cin>>n;
			ll pd=0;
			for(ll i=1;i<=n;i++)
			{
				ll x;
				cin>>x;
				if((i-1)*2>=x||(n-i)*2>=x)pd=1;
			}
			if(pd)cout<<"NO"<<endl;
			else cout<<"YES"<<endl;
		}
	}

C.Cirno and Operations

思路:只有两种操作,其实第二种变成差分数组,反转之前和之后,值只有正负之分,绝对值是一样的,数据范围小,暴力枚举即可,其实每次取个最大abs(anal)其实应该就可以了

	#include<iostream>
	#include<queue>
	#include<map>
	#include<set>
	#include<vector>
	#include<algorithm>
	#include<deque>
	#include<cctype>
	#include<string.h>
	#include<math.h>
	#include<time.h>
	#include<random>
	#include<functional>
	#include<stack>
	#include<string>
	#define ll                                  long long 
	#define lowbit(x) (x & -x)
	#define endl "\n"//                           交互题记得删除
	using namespace std;
	mt19937 rnd(time(0));
	const ll mod = 998244353;
	//const ll p=rnd()%mod;
	ll ksm(ll x, ll y)
	{
		ll ans = 1;
		while (y)
		{
			if (y & 1)
			{
				ans = ans % mod * (x % mod) % mod;
			}
			x = x % mod * (x % mod) % mod;
			y >>= 1;
		}
		return ans % mod % mod;
	}
	ll gcd(ll x, ll y)
	{
		if (y == 0)
			return x;
		else
			return gcd(y, x % y);
	}
	void fio()
	{
		ios::sync_with_stdio(0);
		cin.tie(0);
		cout.tie(0);
	}
	struct s
	{
		ll l,r;
		bool operator<(const s&a)
		{
		}
	};
	ll a[5450000];
	int main()
	{
		fio();
		ll t;
		cin>>t;
		while(t--)
		{
			ll n;
			cin>>n;
			ll ans=-1e18;
			ll sum=0;
			for(ll i=1;i<=n;i++)
			{
				cin>>a[i];
				sum+=a[i];
			}
			ans=sum;
			ll l=1,r=n;
			while(1)
			{
				sum=0;
				if(l==r)break;
				if(a[r]-a[l]>=0)
				{
					for(ll i=r;i>=l+1;i--)
					{
						a[i]=a[i]-a[i-1];
					}
					l++;
				}
				else 
				{
					
					for(ll i=l;i<=(l+r)>>1;i++)
					{
						swap(a[i],a[r-i+l]);	
					}
				
				}
				for(ll i=l;i<=r;i++)
				{
					sum+=a[i];
				}
				ans=max(ans,sum);
			}
			cout<<ans<<endl;
		}
	}

D.Balanced Tree

思路:本题从树的角度去考虑,如果儿子中的最大值小于等于父亲的值,其实没有必要修改父亲的,但是得传递修改值;如果父亲的值小于儿子的值,其修改值将是所有大于父亲的儿子的值-父亲的值之差的和。所以我们可以发现一个节点的值不能太大也不能太小,所以我们尽量往儿子中的最大值去靠即可(越大,答案越不优;越小,答案只会大于等于最优答案),然后分情况改变下修改值即可。

	#include<iostream>
	#include<queue>
	#include<map>
	#include<set>
	#include<vector>
	#include<algorithm>
	#include<deque>
	#include<cctype>
	#include<string.h>
	#include<math.h>
	#include<time.h>
	#include<random>
	#include<functional>
	#include<stack>
	#include<string>
	#define ll                                  long long 
	#define lowbit(x) (x & -x)
	#define endl "\n"//                           交互题记得删除
	using namespace std;
	mt19937 rnd(time(0));
	const ll mod = 998244353;
	//const ll p=rnd()%mod;
	ll ksm(ll x, ll y)
	{
		ll ans = 1;
		while (y)
		{
			if (y & 1)
			{
				ans = ans % mod * (x % mod) % mod;
			}
			x = x % mod * (x % mod) % mod;
			y >>= 1;
		}
		return ans % mod % mod;
	}
	ll gcd(ll x, ll y)
	{
		if (y == 0)
			return x;
		else
			return gcd(y, x % y);
	}
	void fio()
	{
		ios::sync_with_stdio(0);
		cin.tie(0);
		cout.tie(0);
	}
	struct s
	{
		ll l,r;
		bool operator<(const s&a)
		{
		}
	};
	ll a[5450000];
	vector<ll>g[250000];
	ll ans=0;
	map<ll,pair<ll,ll>>z;
	ll dfs(ll x,ll f)
	{
		ll xg=0;
		vector<pair<ll,ll>>k;
		ll l=z[x].first;
		ll r=z[x].second;
		ll u=0;
		ll z=0;
		for(auto j:g[x])
		{
			if(j==f)continue;
			xg+=dfs(j,x);
			u=max(u,a[j]);
			if(a[j]>=r)z+=a[j]-r;
		}
		if(u>=l&&u<=r)
		{	
			a[x]=u;
			return xg;
		}
		else if(u<=l)
		{
			a[x]=l;
			return xg;
		}
		else  
		{
			a[x]=r;
			return xg+z;
		}
	};
	int main()
	{
		fio();
		ll t;
		cin>>t;
		while(t--)
		{
			z.clear();
			ans=0;
			ll n;
			cin>>n;
			for(ll i=1;i<=n;i++)
			{
				g[i].clear();
				ll l,r;
				cin>>l>>r;
				z[i]={l,r};
			}
			for(ll i=1;i<n;i++)
			{
				ll l,r;
				cin>>l>>r;
				g[l].push_back(r);
				g[r].push_back(l);
			}
			cout<<dfs(1,0)+a[1]<<endl;
		}
	}

E1.The Game (Easy Version)

思路:没往LCA去想,但是这道题LCA好做,可能答案也是LCA?满足LCA要求后,我们先进行排序,优先值,其次是深度,这个很重要。最大值的所有点不考虑,如果倒序遍历过程中,该值和上一个值不相同,我们就去遍历上一个所有点,如果该点和上一个值点的所有点LCA都是该点则继续,否则解就是该点,break;如果相同,由于进行深度排序了,此时该点的深度比他小,如果该点和上一个点的LCA,只要不是该点,则该点即是答案,break,否则重复上述步骤即可,显然不会TLE

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<string>
#define ll                                  long long 
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
ll ksm(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1)
		{
			ans = ans % mod * (x % mod) % mod;
		}
		x = x % mod * (x % mod) % mod;
		y >>= 1;
	}
	return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
	if (y == 0)
		return x;
	else
		return gcd(y, x % y);
}
void fio()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}
ll dep[450000];
struct s
{
	ll l, r;
	bool operator<(const s& a)
	{
		if (r != a.r)
			return r < a.r;
		else return dep[l] < dep[a.l];
	}
}p[405000];
ll a[450000];
vector<ll>g[450000];
vector<ll>k[450000];
ll fa[450000][36];
ll lca(ll x, ll y)
{
	if (dep[x] < dep[y])swap(x, y);
	ll dis = dep[x] - dep[y];
	for (ll i = 30; i >= 0; i--)
	{
		if ((1ll << i) <= dis)
		{
			dis -= 1ll << i;
			x = fa[x][i];
		}
	}
	if (x == y)
		return x;
	for (ll i = 30; i >= 0; i--)
	{
		if (fa[x][i] != fa[y][i])x = fa[x][i], y = fa[y][i];
	}
	return fa[x][0];
}
void dfs(ll x, ll f)
{
	dep[x] = dep[f] + 1;
	fa[x][0] = f;
	for (ll i = 1; i <= 31; i++)
	{
		fa[x][i] = fa[fa[x][i - 1]][i - 1];
	}
	for (auto j : g[x])
	{
		if (j == f)continue;
		dfs(j, x);
	}
}
int main()
{
	fio();
	ll t;
	cin >> t;
	while (t--)
	{
		ll n;
		cin >> n;
		for (ll i = 1; i <= n; i++)
		{
			cin >> a[i];
			p[i].l = i;
			k[i].clear();
			p[i].r = a[i];
			g[i].clear();
		}
		for (ll i = 1; i <= n; i++)
		{
			k[a[i]].push_back(i);
		}
		for (ll i = 1; i < n; i++)
		{
			ll l, r;
			cin >> l >> r;
			g[l].push_back(r);
			g[r].push_back(l);
		}
		dfs(1, 0);
		sort(p + 1, p + 1 + n);
		ll ans = 0;
		ll flag = p[n].r;
		//for(ll i=1;i<=n;i++)cout<<p[i].l<<endl;
		for (ll i = n - 1; i >= 1; i--)
		{
			//cout<<p[i].l<<endl;
			if (p[i].r == p[n].r)continue;
			if (flag != p[i].r)
			{
				for (auto j : k[flag])
				{
					//if (flag == 3)cout << j << endl;
					ll u = lca(p[i].l, j);
					if (u == p[i].l)continue;
					else ans = p[i].l;
				}
			}
			else if (flag == p[i].r)
			{
				if (lca(p[i + 1].l, p[i].l) == p[i].l)continue;
				else ans = p[i].l;
			}
			if (ans)break;
			flag = p[i].r;
		}
		cout << ans << endl;
	}
}
posted @   长皆  阅读(248)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示