A:给定一个序列,一个操作是向其中任何一个位置插入一个数,问至少需要多少次操作才能保证两两之间的max(a[i],a[i+1])/min(a[i],a[i+1])<=2。
假设在i和i+1之间插入一个数,这个操作并不会影响到其他,所以我们可以线性的考虑整个序列。
那么我们现在只需要考虑如果a和b,max(a,b)/min(a,b)>2的话怎么办。
只需要一直在a,b之间插入a的2次方倍,直到满足条件就OK了。
1 #include<iostream> 2 using namespace std; 3 int main(void){ 4 int t; 5 cin>>t; 6 while(t--){ 7 int a[100]; 8 int n; 9 cin>>n; 10 for(int i=0;i<n;i++){ 11 cin>>a[i]; 12 } 13 int res=0; 14 for(int i=0;i<n-1;i++){ 15 int t1=min(a[i],a[i+1]),t2=max(a[i],a[i+1]); 16 while(t1*2<t2){ 17 res++; 18 t1*=2; 19 } 20 } 21 cout<<res<<endl; 22 } 23 return 0; 24 }
B:给定一串序列,按模3的余数分类,每次操作可以将其中一个数加一,问最少多少次操作可以保证每一类的数目相等(保证总数模3等于0)
首先计算出每一类的数目,0->1,1->2,2->0,都只需要一次操作。
直接计算即可。
1 #include<iostream> 2 using namespace std; 3 int main(void){ 4 int t; 5 cin>>t; 6 while(t--){ 7 int n; 8 scanf("%d",&n); 9 int cnt[3]={0,0,0}; 10 for(int i=0;i<n;i++){ 11 int tmp; 12 scanf("%d",&tmp); 13 cnt[tmp%3]++; 14 } 15 int s=(cnt[0]+cnt[1]+cnt[2])/3; 16 int res=0; 17 for(int i=0;i<3;i++){ 18 if(cnt[i]<s){ 19 int tmp=s-cnt[i]; 20 res+=tmp; 21 cnt[(i-1+3)%3]-=tmp; 22 }else{ 23 int tmp=cnt[i]-s; 24 res+=tmp; 25 cnt[(i+1+3)%3]+=tmp; 26 } 27 } 28 cout<<res<<endl; 29 } 30 return 0; 31 }
C:给定一个数x,问x=a^3+b^3的a和b是否存在。
x的范围是1e12,开三次方就是1e4,所以可以预处理出1~1e4的三次方。
然后对于每一个x,枚举a,在预处理数组中二分查找b。
时间复杂度为1e4*log(1e4)。
1 #include<cmath> 2 #include<algorithm> 3 #include<iostream> 4 using namespace std; 5 typedef long long LL; 6 const int N=10100; 7 int cnt; 8 LL a[N]; 9 bool is_ok(LL x){ 10 int l=0,r=cnt-1; 11 while(l<r){ 12 int mid=l+r+1>>1; 13 if(a[mid]>x) r=mid-1; 14 else l=mid; 15 } 16 return a[r]==x; 17 } 18 int main(void){ 19 for(LL i=1;i<=10010;i++){ 20 a[cnt++]=i*i*i; 21 } 22 int t; 23 cin>>t; 24 while(t--){ 25 bool flag=false; 26 LL x; 27 cin>>x; 28 for(LL i=1;i*i*i<x;i++){ 29 LL a=i*i*i; 30 LL b=x-a; 31 if(is_ok(b)){ 32 flag=true; 33 } 34 } 35 if(flag) cout<<"YES"<<endl; 36 else cout<<"NO"<<endl; 37 } 38 return 0; 39 }
D:给定一个排列,每次选择最大的那个数,建立一棵二叉树,输出每个节点的深度。
考试的时候想的是先建出一棵树,然后再层序遍历,可惜我用的是静态数组(因为方便),那么假设他给你的就是单单的一条链的话,100个节点就需要2^100的数组长度(显然不行)。
我们在建树的时候存储的是它在原数组中的位置,那么我们可以直接传一个depth参数进去,对于每一个节点直接确定他的深度,就不存在空间的问题了。
1 #include<iostream> 2 #include<queue> 3 #include<climits> 4 #include<cstring> 5 using namespace std; 6 typedef pair<int,int> PII; 7 const int N=1110; 8 int a[N],res[N]; 9 int b[N*4]; 10 void build(int root,int l,int r){ 11 if(l>r) return ; 12 int ma=a[l],id=l; 13 for(int i=l;i<=r;i++){ 14 if(a[i]>ma){ 15 ma=a[i],id=i; 16 } 17 } 18 b[root]=id; 19 build(root*2+1,l,id-1); 20 build(root*2+2,id+1,r); 21 } 22 int main(void){ 23 int t; 24 cin>>t; 25 while(t--){ 26 memset(b,0,sizeof b); 27 int n; 28 cin>>n; 29 for(int i=1;i<=n;i++){ 30 cin>>a[i]; 31 } 32 build(0,1,n); 33 queue<int> q; 34 q.push(0); 35 int deep=0; 36 while(q.size()){ 37 int s=q.size(); 38 for(int i=0;i<s;i++){ 39 int x=q.front(); 40 q.pop(); 41 res[b[x]]=deep; 42 if(b[x*2+1]!=0){ 43 q.push(x*2+1); 44 } 45 if(b[x*2+2]!=0){ 46 q.push(x*2+2); 47 } 48 } 49 deep++; 50 } 51 for(int i=1;i<=n;i++){ 52 cout<<res[i]<<" "; 53 } 54 cout<<endl; 55 } 56 return 0; 57 }
1 #include<iostream> 2 #include<queue> 3 #include<climits> 4 #include<cstring> 5 using namespace std; 6 typedef pair<int,int> PII; 7 const int N=1010; 8 int a[N],d[N]; 9 void build(int l,int r,int depth){ 10 if(l>r) return ; 11 int id=l; 12 for(int i=l;i<=r;i++){ 13 if(a[i]>a[id]){ 14 id=i; 15 } 16 } 17 d[id]=depth; 18 build(l,id-1,depth+1); 19 build(id+1,r,depth+1); 20 } 21 int main(void){ 22 int t; 23 cin>>t; 24 while(t--){ 25 int n; 26 cin>>n; 27 for(int i=1;i<=n;i++){ 28 cin>>a[i]; 29 } 30 build(1,n,0); 31 for(int i=1;i<=n;i++){ 32 cout<<d[i]<<" "; 33 } 34 cout<<endl; 35 } 36 return 0; 37 }
E(补):给定n个选手和他们各自的value,每次随机选定两个选手,value大的获胜并获得败者的全部value,如果两者value相等,胜负将随机。共进行n-1次比赛,每次仅仅选择手中还有value的上场。
输出有最终可能获胜的人的人数和所有最终有可能获胜的人的编号(从小到大)。
将选手按value排序并记住他们的id,如果 i 赢完了小于他的全部的选手的value,还是无法战胜最小的大于他的,那么 i 获胜的几率就为0.
如此便可以直接用前缀和解决这个问题。
1 #include<iostream> 2 #include<queue> 3 #include<climits> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 typedef long long LL; 8 const LL N=2e5+10; 9 struct node{ 10 LL v,id; 11 bool operator< (node& t){ 12 return v<t.v; 13 } 14 }a[N]; 15 LL sum[N]; 16 int main(void){ 17 LL t; 18 cin>>t; 19 while(t--){ 20 LL n; 21 vector<LL> res; 22 cin>>n; 23 for(LL i=1;i<=n;i++){ 24 cin>>a[i].v; 25 a[i].id=i; 26 } 27 sort(a+1,a+n+1); 28 for(int i=1;i<=n;i++){ 29 sum[i]=sum[i-1]+a[i].v; 30 } 31 res.push_back(a[n].id); 32 for(LL i=n-1;i>=1;i--){ 33 if(sum[i]>=a[i+1].v){ 34 res.push_back(a[i].id); 35 }else{ 36 break; 37 } 38 } 39 sort(res.begin(),res.end()); 40 cout<<res.size()<<endl; 41 for(auto x:res){ 42 cout<<x<<" "; 43 } 44 cout<<endl; 45 } 46 return 0; 47 }