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.