Solution Set -「CF 1485」

「CF 1485A」Add and Divide

Link.

贪心。枚举 \([b,b+\log_{2}\text{range}]\) 然后取个 \(\min\)

#include<cstdio>
#include<algorithm>
using namespace std;
int t,a,b,ans;
int search(int bas)
{
	if(bas>1)
	{
		int tmp=a,res=0;
		while(tmp>0)
		{
			tmp/=bas;
			res++;
		}
		return res;
	}
	else	return 1e9;
}
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d %d",&a,&b);
		if(a==b)	printf("%d\n",2);
		else if(a<b)	printf("%d\n",1);
		else
		{
			ans=1e9;
			for(int i=b;i<=b+233;++i)	ans=min(ans,search(i)+i-b);
			printf("%d\n",ans);
		}
	}
	return 0;
}

「CF 1485B」Replace and Keep Sorted

Link.

每个元素都可以上下摇摆于是预处理前缀差分和和后缀差分和(因为是 strictly increasing 所以要减 \(1\))即可。

#include<cstdio>
int n,m,k,a[100010],fro[100010],rea[100010];
void pre()
{
	for(int i=1;i<=n;++i)	fro[i]=a[i]-a[i-1]-1;
	for(int i=n;i>=1;--i)	rea[i]=a[i+1]-a[i]-1;
	for(int i=1;i<=n;++i)	fro[i]+=fro[i-1];
	for(int i=n;i>=1;--i)	rea[i]+=rea[i+1];
}
int main()
{
	scanf("%d %d %d",&n,&m,&k);
	for(int i=1;i<=n;++i)	scanf("%d",&a[i]);
	pre();
	while(m--)
	{
		int l,r;
		scanf("%d %d",&l,&r);
		printf("%d\n",k-a[r]+a[l]-1+fro[r]-fro[l]+rea[l]-rea[r]);
	}
	return 0;
}

「CF 1485C」Floor and Mod

Link.

\[a\bmod b=\lfloor\frac{a}{b}\rfloor=k \\ \rightarrow a=kb+k\rightarrow a=(b+1)k\rightarrow k=\frac{a}{b+1} \\ k<b\rightarrow k^{2}<k(b+1)=a\le x\rightarrow 1\le k\le\sqrt{x} \\ 1\le a\le x\rightarrow 1\le(b+1)k\le x\rightarrow1\le b\le\frac{x}{k}-1 \\ \rightarrow\text{ans}=\sum_{k=1}^{\sqrt{x}}\max(0,\min(y,\frac{x}{k}-1)-k) \]

#include<cstdio>
#include<algorithm>
using namespace std;
const long long zero=0ll;
long long t,x,y,ans;
int main()
{
	scanf("%lld",&t);
	while(t--)
	{
		scanf("%lld %lld",&x,&y);
		ans=0;
		for(long long i=1;i*i<=x;++i)	ans+=max(zero,min(y,x/i-1)-i);
		printf("%lld\n",ans);
	}
	return 0;
}

「CF 1485D」Multiples and Power Differences

Link.

  • \((i+j)\bmod 2=1\)\(b_{i,j}=\text{lcm}(1,\cdots,16)\)
  • \((i+j)\bmod 2=0\)\(b_{i,j}=\text{lcm}(1,\cdots,16)+a_{i,j}^{4}\)
#include<cstdio>
int n,m,x;
int main()
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;++i)
	{
		for(int j=1;j<=m;++j)
		{
			scanf("%d",&x);
			if((i+j)&1)	printf("%d ",720720);
			else	printf("%d ",720720+x*x*x*x);
		}
		printf("\n");
	}
	return 0;
}

「CF 1485E」Move and Swap

Link.

blue 因为就是一直往下跑,所以一次操作在哪里不影响。

于是设 \(f_{u}\) 为操作完毕后 red 跑到 \(u\) 的 maximum value。

  • \(v\in\text{son}(u)\) 为 red:此时没发生 swapping,\(f_{u}=f_{v}+|a_{u}-a_{v}|\)
  • \(v\in\text{son}(u)\) 为 blue:此时发生了 swapping,那么枚举 \(v\) 的同层结点 \(anov\)\(f_{u}=f_{anov}+|a_{u}-a_{anov}|\)
#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
const long long INF=1e18;
vector<int> e[200010],same[200010];
int t,n,dep[200010],fa[200010],leaf;
long long a[200010],f[200010];
void dfs(int x,int las)
{
	dep[x]=dep[las]+1;
	fa[x]=las;
	leaf=max(leaf,dep[x]);
	for(int i=0;i<e[x].size();++i)
	{
		int y=e[x][i];
		if(y^las)	dfs(y,x);
	}
}
void DP(int d)
{
	for(int i=d;i>1;--i)
	{
		long long mn=INF,mx=-INF,one=-INF,ano=-INF;
		for(int j=0;j<same[i].size();++j)
		{
			mn=min(mn,a[same[i][j]]);
			mx=max(mx,a[same[i][j]]);
		}
		for(int j=0;j<same[i].size();++j)	f[fa[same[i][j]]]=max(f[fa[same[i][j]]],max(a[same[i][j]]-mn,mx-a[same[i][j]])+f[same[i][j]]);
		for(int j=0;j<same[i].size();++j)
		{
			one=max(one,f[same[i][j]]+a[same[i][j]]);
			ano=max(ano,f[same[i][j]]-a[same[i][j]]);
		}
		for(int j=0;j<same[i].size();++j)	f[fa[same[i][j]]]=max(f[fa[same[i][j]]],max(one-a[same[i][j]],ano+a[same[i][j]]));
	}
}
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		for(int i=2;i<=n;++i)
		{
			int x;
			scanf("%d",&x);
			e[x].push_back(i);
			e[i].push_back(x);
		}
		for(int i=2;i<=n;++i)	scanf("%d",&a[i]);
		dfs(1,0);
		for(int i=1;i<=n;++i)	same[dep[i]].push_back(i);
		DP(leaf);
		printf("%lld\n",f[1]);
		for(int i=1;i<=n;++i)
		{
			f[i]=dep[i]=fa[i]=0;
			same[i].clear();
			e[i].clear();
		}
		leaf=0;
	}
	return 0;
}

「CF 1485F」Copy or Prefix Sum

Link.

posted @ 2021-02-17 21:20  cirnovsky  阅读(51)  评论(0编辑  收藏  举报