TA
题意:问要插入最少多少个数让整个数组满足题目的条件,即相邻两个数之间大小补相差二倍
idea:遍历一遍,对每两个相邻的数,看看较小的数*2多少次后可以大于等于较大的数,利用位运算方便点
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define LL long long
#define N 555
#define INF 0x3f3f3f3f
using namespace std;
long long ans = 0;
int n,t,a[N],last,maxx,minn;
int main()
{
cin>>t;
while(t--)
{
ans = 0;
scanf("%d",&n);
scanf("%d",&a[1]);
for(int i=2;i<=n;i++)
{
scanf("%d",&a[i]);
if( a[i]<a[i-1] )
{
minn = a[i];
maxx = a[i-1];
}
else
{
minn = a[i-1];
maxx = a[i];
}
while( (minn<<1) < maxx )
{
ans++;
minn<<=1;
}
}
printf("%lld\n",ans);
}
return 0;
}
TB
题意:数组有n个数,n是3的倍数,你一次可以让一个数加一,问最少多少步操作后可以使得数组内各个数对3取模后得到的余数的个数一样,即平均。
idea:先统计,然后对比余数为0,1,2的数与n/3的大小关系,2不够从1补,1不够从0补,0不够从2补,循环两遍(颇有锻环成链的感觉)就可了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define LL long long
#define N 40000
#define INF 0x3f3f3f3f
using namespace std;
int t,n,m,ans,a[5],s;
void work()
{
if( a[2]<m )
{
ans += (m-a[2]);
a[1] -= (m-a[2]);
a[2] = m;
}
if( a[1]<m )
{
ans += (m-a[1]);
a[0] -= (m-a[1]);
a[1] = m;
}
if( a[0]<m )
{
ans += (m-a[0]);
a[2] -= (m-a[0]);
a[0] = m;
}
}
int main()
{
// freopen("in.txt","r",stdin);
cin>>t;
while(t--)
{
ans = 0;
a[1] = 0;
a[2] = 0;
a[0] = 0;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&s);
a[ s%3 ]++;
}
m = n/3;
work();
work();
printf("%d\n",ans);
}
return 0;
}
TC
题意:问每个数能不能拆成两个数的立方的和
idea:看一眼数据范围最大不过10000的立方,考虑先打一个1到10000的立方的表,然后对每一个数n,再枚举一遍其中一个数的立方和,判断相减得到的另一个数是否为立方数即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#define LL long long
#define N 40000
#define INF 0x3f3f3f3f
using namespace std;
map<LL,int> q;
LL t,n,m,a[10100],tag;
void FI()
{
for(int i=1;i<=10001;i++)
{
a[i] = i*i;
a[i] *= i;
q[ a[i] ] = 1;
}
}
int main()
{
// freopen("in.txt","r",stdin);
cin>>t;
FI();
while(t--)
{
bool pd = false;
scanf("%lld",&n);
for(int i=10001;i>=1;i--)
{
if( a[i]<=n )
{
tag = i;
break;
}
}
for(int i=tag;i>=1&&pd==false;i--)
{
if( q.count( n-a[i] ) > 0 )
{
pd = true;
break;
}
}
if( pd ) printf("YES\n");
else printf("NO\n");
}
return 0;
}
TD
题意:给出一数列,要求将区间内的最大值作为数的根节点,最大值左右部分分别作为左右子树建树,求每个数所对应的节点所在的深度。
idea:线段树查找区间最大值
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define LL long long
#define N 200
#define INF 0x3f3f3f3f
using namespace std;
int T,n,a[N],sum = 0,ans[N],tag,maxx,xu[N];
struct node
{
int l,r,val;
}t[N*4];
void build(int p,int l,int r)
{
t[p].l = l,t[p].r = r;
int ls = p<<1,rs = (p<<1)|1,mid = (l+r)>>1;
if( l!=r )
{
build(ls,l,mid);
build(rs,mid+1,r);
t[p].val = max( t[ls].val , t[rs].val );
}
else t[p].val = a[l];
}
int check(int p,int l,int r)
{
int ls = p<<1,rs = p<<1|1,mid = (t[p].l+t[p].r)>>1;
if( l==t[p].l && r==t[p].r ) return t[p].val;
if( r<=mid ) return check(ls,l,r);
else if( l>mid ) return check(rs,l,r);
else return max( check(ls,l,mid) , check(rs,mid+1,r) );
}
void work(int p,int h,int l,int r)
{
int pos;
ans[p] = h;
if( l==r ) return ;
if( l<p )
{
pos = check(1,l,p-1);
pos = xu[ pos ];
work(pos,h+1,l,p-1);
}
if( r>p )
{
pos = check(1,p+1,r);
pos = xu[ pos ];
work(pos,h+1,p+1,r);
}
return ;
}
int main()
{
// freopen("in.txt","r",stdin);
cin>>T;
while(T--)
{
memset(xu,0,sizeof(xu));
memset(ans,0,sizeof(ans));
memset(t,0,sizeof(t));
maxx = -1;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
xu[ a[i] ] = i;
if( a[i]>maxx )
{
tag = i;
maxx = a[i];
}
}
build(1,1,n);
work(tag,0,1,n);
for(int i=1;i<=n;i++) printf("%d ",ans[i]);
cout<<endl;
}
return 0;
}
TE
题意:给出若干个人的初始代币数,随机挑选2个代币数不为0的人对决,代币数多的一方获胜并拿走败方的所有代币(相同时随机一个胜者),最后剩下代币数不为0的一人赢得比赛,求有机会赢得比赛的人的编号。
idea:先排序。首先,如果一个人能赢,那么金币数大于他的也一定能赢。其次,一个人可以赢下所有金币数比他小的,因此我们可以求一个前缀和,只要他能赢下比他大的第一个人且后一个人能赢,当前这个人一定能赢。我们只要找第一个不能赢的人就好啦,比他大的一定能赢,比他小的一定赢不了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#define LL long long
#define N 40000
#define INF 0x3f3f3f3f
using namespace std;
int sum,ans[201000],t,n,tag;
LL q[201000];
struct node
{
int val,xu;
}e[200100];
bool cmp(node x,node y)
{
return x.val<y.val;
}
void work()
{
for(int i=n-1;i>=1;i--)
{
if( q[i] < e[i+1].val-e[i].val )
{
tag = i;
break;
}
}
sum = n-tag;
for(int i=1;i<=sum;i++)
{
ans[i] = e[n-i+1].xu;
}
sort(ans+1,ans+sum+1);
}
int main()
{
cin>>t;
while(t)
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&e[i].val);
sort(e+1,e+n+1,cmp);
for(int i=1;i<=n;i++) q[i] = q[i-1] + e[i].val;
work();
cout<<sum<<endl;
for(int i=1;i<=sum;i++)
cout<<ans[i]<<" ";
cout<<endl;
}
return 0;
}