Codeforces Round #702

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 }
原文地址:https://www.cnblogs.com/greenofyu/p/14416979.html