CodeForces - 1490
A - Dense Array
const int maxn=2e6+7;
const int INF=0x3f3f3f3f;
const ll INFF=1e18;
int t,n,a[maxn];
int main()
{
scanf("%d",&t);
while(t--)
{
int ans=0;
scanf("%d",&n);
rep(i,1,n)scanf("%d",&a[i]);
rep(i,1,n-1)
{
int maxx=max(a[i],a[i+1]);
int minn=min(a[i],a[i+1]);
while(maxx>2*minn)
{
minn*=2;
ans++;
}
}
W(ans);
}
return 0;
}
B - Balanced Remainders
由多的给少的,最后达到平衡
const int maxn=2e6+7;
const int INF=0x3f3f3f3f;
const ll INFF=1e18;
int t,n,a[maxn],c0,c1,c2,ans;
void solve()
{
if (c0>n/3)
{
c1+=c0-n/3;
ans+=c0-n/3;
c0=n/3;
}
if (c1>n/3)
{
c2+=c1-n/3;
ans+=c1-n/3;
c1=n/3;
}
if (c2>n/3)
{
c0+=c2-n/3;
ans+=c2-n/3;
c2=n/3;
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
c0=0,c1=0,c2=0,ans=0;
scanf("%d",&n);
rep(i,1,n)
{
scanf("%d",&a[i]);
if (a[i]%3==0)c0++;
if (a[i]%3==1)c1++;
if (a[i]%3==2)c2++;
}
while(!(c0==c1&&c1==c2))
{
solve();
}
W(ans);
}
return 0;
}
C - Sum of Cubes
O(1e4)预处理出所有的三次方数
const int maxn=2e6+7;
const int INF=0x3f3f3f3f;
const ll INFF=1e18;
ll t,x;
map<ll,int> M;
bool find_(ll x)
{
for (ll i=1;i<=10000;i++)
{
if (x<=i*i*i)break;
if (M[x-i*i*i])return true;
}
return false;
}
int main()
{
scanf("%lld",&t);
for (ll i=1;i<=10000;i++)M[i*i*i]=1;
while(t--)
{
scanf("%lld",&x);
if (find_(x))printf("YES\n");
else printf("NO\n");
}
return 0;
}
D - Permutation Transformation
递归:每遇到一个最大值,就分两段,并深度加1
const int maxn=2e6+7;
const int INF=0x3f3f3f3f;
const ll INFF=1e18;
int t,n,a[maxn],ans[maxn];
void solve(int num,int l,int r)
{
int maxx=0,pos=-1;
if (l>r)return;
rep(i,l,r)
{
if (a[i]>maxx)
{
maxx=a[i];
pos=i;
}
}
ans[pos]=num;
solve(num+1,l,pos-1);
solve(num+1,pos+1,r);
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
rep(i,1,n)scanf("%d",&a[i]);
solve(0,1,n);
rep(i,1,n)printf("%d ",ans[i]);puts("");
}
return 0;
}
E - Accidental Victory
反向遍历,对于位置为i的人
如果前缀和sum[i]>=a[i+1],就有机会赢
如果sum[i]<a[i+1],不论如何都赢不了a[j](j>i),这种情况直接break因为再前面的人更不可能赢
const int maxn=2e6+7;
const int INF=0x3f3f3f3f;
const ll INFF=1e18;
struct node
{
ll x;
int id;
}p[maxn];
bool cmp(node a,node b)
{
return a.x<b.x;
}
int n,t;
ll sum[maxn];
vector<int>ans;
int main()
{
scanf("%d",&t);
while(t--)
{
ans.clear();
scanf("%d",&n);
rep(i,1,n)
{
scanf("%lld",&p[i].x);
p[i].id=i;
}
sort(p+1,p+1+n,cmp);
rep(i,1,n)sum[i]=sum[i-1]+p[i].x;
ans.pb(p[n].id);
for (int i=n-1;i>=1;i--)
{
if (sum[i]>=p[i+1].x)ans.pb(p[i].id);
else break;
}
sort(ans.begin(),ans.end());
W(ans.size());
repp(i,0,ans.size())printf("%d ",ans[i]);puts("");
}
return 0;
}
F - Equalize the Array
预处理出每个数量的人共有多少组
比如数组
a
a
a=[1,1,1,2,2,3,3],那么
n
u
m
{
1
,
2
,
3
}
=
{
0
,
2
,
1
}
num\{1,2,3\}=\{0,2,1\}
num{1,2,3}={0,2,1}
令
C
=
i
,
a
n
s
=
0
C=i,ans=0
C=i,ans=0
对于
∀
j
<
i
\forall j<i
∀j<i必须全部消除,
a
n
s
+
=
∑
j
=
1
i
−
1
(
n
u
m
[
j
]
∗
j
)
ans+=\sum_{j=1}^{i-1}(num[j]*j)
ans+=∑j=1i−1(num[j]∗j)
对于
∀
j
<
i
\forall j<i
∀j<i必须全部消除到
i
i
i个才可以,可以用一个变量
p
r
e
pre
pre和后缀和去完成
两部分加起来,不断取min就是答案
const int maxn=2e6+7;
const int INF=0x3f3f3f3f;
const ll INFF=1e18;
int t,n,a[maxn],m,b[maxn],c[maxn],num[maxn],sum[maxn],ans,num1[maxn],bac[maxn];
int query(int x)
{
return lower_bound(b+1,b+1+m,x)-b;
}
int main()
{
scanf("%d",&t);
while(t--)
{
m=0;ans=INF;
scanf("%d",&n);
rep(i,1,n)scanf("%d",&a[i]);
rep(i,0,n+1)num1[i]=num[i]=sum[i]=bac[i]=0;
sort(a+1,a+1+n);
rep(i,1,n)if (i==1||a[i]!=a[i-1])b[++m]=a[i];
rep(i,1,n)
{
c[i]=query(a[i]);
num1[c[i]]++;
}
rep(i,1,n)num[num1[i]]++;
rep(i,1,n)sum[i]=sum[i-1]+i*num[i];
for (int i=n;i>=1;i--)bac[i]=bac[i+1]+num[i];
int pre=0;
for (int i=n;i>=1;i--)
{
pre+=bac[i+1];
ans=min(ans,pre+sum[i-1]);
}
W(ans);
}
return 0;
}
G - Old Floppy Drive
分三种情况:
1.如果sum[n]<=0并且最大的前缀和都比x小,则输出-1
2.如果最大的前缀和大于等于x,那么一定是一轮就可以输出的
3.需要进行多轮,那么先让x减去最大的前缀和,然后整除算出需要多少轮
接下来二分找出具体位置
假设前缀和数组为1,0,3,5,4
显然
如果取不到1,更不可能取到0,意味着可以修改为递增数组1,1,3,5,5
const int maxn=2e6+7;
const int INF=0x3f3f3f3f;
const ll INFF=1e18;
ll t,n,m,a[maxn],x[maxn],sum[maxn],maxx[maxn];
int main()
{
scanf("%lld",&t);
while(t--)
{
maxx[0]=-INFF;
scanf("%lld%lld",&n,&m);
rep(i,1,n)scanf("%lld",&a[i]),sum[i]=sum[i-1]+a[i],maxx[i]=max(maxx[i-1],sum[i]);
rep(i,1,m)
{
scanf("%lld",&x[i]);
if (sum[n]<=0&&maxx[n]<x[i])printf("%d ",-1);
else if (maxx[n]>=x[i])
{
ll ans=lower_bound(maxx+1,maxx+1+n,x[i])-maxx-1;
printf("%lld ",ans);
}
else
{
ll k=(x[i]-maxx[n]+sum[n]-1)/sum[n];
ll ans=n*k;
ans+=lower_bound(maxx+1,maxx+1+n,x[i]-sum[n]*k)-maxx-1;
printf("%lld ",ans);
}
}
puts("");
}
return 0;
}