zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    HDU 1540 Tunnel Warfare (线段树区间合并)
    P2258 子矩阵
    P5021 赛道修建
    P4084 [USACO17DEC]Barn Painting
    P3914 染色计数
    比赛用模板
    P3594 [POI2015]WIL-Wilcze doły
    P5022 旅行
    P3952 时间复杂度
    P3960 列队
  • 原文地址:https://www.cnblogs.com/greenofyu/p/14416979.html
Copyright © 2011-2022 走看看