CF补题大作战#1

发布于 2022-10-31  181 次阅读


碎碎念

忽然想起这个又断更了许久的blog,断更的起因是ll第一次集中的时候讲的话

”不要满足于每次打完cf,过掉了前面几道题,然后水出一篇题解“(大致意思)

自我总结下来,平时提升自我的方法只有两种,或者说一种

一是去学习新的算法,用这个新的算法去解题

二是去补题,补之前的比赛中遇到的不会做的题

本质上都是去学会自己不会的东西,而简单的打一场比赛,做出几道题,并不能改变什么

想起之前刷到的大佬的经历,一句话印象挺深刻的

”希望以后去翻cf的比赛记录时,看到的是一片绿而不是一片蓝“

距离比赛也只有一个月不到的时间了,所以赛前定一个小目标

在保持一定的vp频率以及每一场vp都补题到金牌线的前提下,补完打过的所有div1以下的题

CF1714F Build a Tree and That Is It

构造一棵树,使其满足节点数为n,dis(1,2)=x,dis(2,3)=y,dis(1,3)=z

solution

很显然的事情是将1作为根,那么x和z分别为2和3的深度

有dis(2,3)=dep(2)+dep(3)-2*dep(lca(2,3))即dep(lca(2,3))=(x+z-y)/2

直接以1,2,3,lca(2,3)四个点为基础构造即可

需要注意的是三种特殊情况即lca(2,3)=1/2/3的情况

#include<bits/stdc++.h>
using namespace std;
int T,n,x,y,z,f[2000010];
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin >> T;
	while(T--)
	{
		cin >> n >> x >> y >> z;
		int k=x+z-y;
		if(k&1||k<0)
		{
			cout << "NO\n";
			continue;
		}
		k/=2;
		if(k>x||k>z)
		{
			cout << "NO\n";
			continue;
		}
		for(int i=1;i<=n;i++)
			f[i]=1;
		int cnt=4;
		if(k==0)
		{
			cnt--;
			f[2]=1,f[3]=1;
			for(int i=1;i<x;i++)
				f[++cnt]=f[2],f[2]=cnt;
			for(int i=1;i<z;i++)
				f[++cnt]=f[3],f[3]=cnt;
		}
		else if(k==x)
		{
			cnt--;
			f[2]=1,f[3]=2;
			for(int i=1;i<k;i++)
				f[++cnt]=f[2],f[2]=cnt;
			for(int i=k+1;i<z;i++)
				f[++cnt]=f[3],f[3]=cnt;
		}
		else if(k==z)
		{
			cnt--;
			f[3]=1,f[2]=3;
			for(int i=1;i<k;i++)
				f[++cnt]=f[3],f[3]=cnt;
			for(int i=k+1;i<x;i++)
				f[++cnt]=f[2],f[2]=cnt;
		}
		else
		{
			f[4]=1,f[2]=4,f[3]=4;
			for(int i=1;i<k;i++)
				f[++cnt]=f[4],f[4]=cnt;
			for(int i=k+1;i<x;i++)
				f[++cnt]=f[2],f[2]=cnt;
			for(int i=k+1;i<z;i++)
				f[++cnt]=f[3],f[3]=cnt;
		}
		if(cnt>n)
		{
			cout << "NO\n";
			continue;
		}
		cout << "YES\n";
		for(int i=2;i<=n;i++)
			cout << i << " " << f[i] << endl;
	}
	return 0;
}

CF1714G Path Prefixes

给你一棵树,其每一条边上有两种权值a,b

对于每一个节点求出,从根节点向该节点引出的最长路径

满足路径上b权值的和不超过根节点到该节点a权值的和

solution

对于每次询问直接倍增去找第一个不符合要求的点即可

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define N 200010
#define K 20
using namespace std;
struct node{int to,a,b;};
int T,n,d[N],f[N][K];
ll s[N][2];
vector<node>e[N];
void dfs(int u,int fa)
{
	for(auto x:e[u])
	{
		int v=x.to;
		if(v==fa)continue;
		s[v][0]=s[u][0]+x.a;
		s[v][1]=s[u][1]+x.b;
		d[v]=d[u]+1,f[v][0]=u;
		for(int i=1;i<K;i++)
			f[v][i]=f[f[v][i-1]][i-1];
		dfs(v,u);
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin >> T;
	while(T--)
	{
		cin >> n;
		for(int i=1;i<=n;i++)
			e[i].clear();
		for(int i=2;i<=n;i++)
		{
			int x,y,z;
			cin >> x >> y >> z;
			e[x].pb({i,y,z});
		}
		dfs(1,0);
		for(int i=2;i<=n;i++)
		{
			int k=i;
			for(int j=K-1;j>=0;j--)
				if(s[f[k][j]][1]>s[i][0])
					k=f[k][j];
			if(s[i][1]<=s[i][0])
				cout << d[i] << " ";
			else cout << d[k]-1 << " ";
		}
		cout << endl;
	}
	return 0;
}