zoukankan      html  css  js  c++  java
  • ACM团队周赛题解(2)

    拉了CF583和CF486的两套div2题目

    还是先贴宏定义部分

    #define MAXN 1000000+5
    #define MOD 1000000007
    #define PI (acos(-1.0))
    #define EPS 1e-6
    #define MMT(s,a) memset(s, a, sizeof s)
    #define GO(i,a,b) for(int i = (a); i < (b); ++i)
    #define GOE(i,a,b) for(int i = (a); i <= (b); ++i)
    #define OG(i,a,b) for(int i = (a); i > (b); --i)
    #define OGE(i,a,b) for(int i = (a); i >= (b); --i)


    A - Asphalting Roads(CF-583A)

    题意就是n条水平路,n条竖直路,构成井字形状。然后第i天会到(xi,yi)这个路口,如果这个路口得两条路都没有被染色,就输出这天并把两个路口都染上颜色,否则跳到下一天。

    输出所有可以染色得天数。

    题目思路:标记遍历即可

     1 int main(){
     2     ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0);
     3     int n,x,y;
     4     cin>>n;
     5     int mp1[55] = {0},mp2[55] = {0};
     6     GO(i,0,n*n){
     7         cin>>x>>y;
     8         if(mp1[x] == 0 && mp2[y] == 0){
     9             cout << i+1 << " ";
    10             mp1[x] = mp2[y] = 1;
    11         }
    12     }
    13     cout << endl;
    14 
    15     return 0;
    16 }

     

    B - Robot's Task(CF-583B)

    题意就是最开始从左往右走,如果现在值Num比a[i]大,则Num+1,否则跳过他,走到尽头如果有数没有经过,则转向再次走,已经走过的地方不能再走。

    Num初始值为0,问至少转向几次。

    思路:模拟即可

     1 int main(){
     2     ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0);
     3     int n;
     4     int a[1005] = {0},vis[1005] = {0};
     5     cin>>n;
     6     GOE(i,1,n){
     7         cin>>a[i];
     8     }
     9     bool flag = true;
    10     int cnt = n,ans = 0,num = 0;
    11     while(cnt > 0){
    12         if(flag){
    13             GOE(i,1,n){
    14                 if(!vis[i] && num >= a[i]){
    15                     vis[i] = 1;
    16                     num++;
    17                     cnt--;
    18                 }
    19             }
    20         }
    21         else{
    22             OGE(i,n,1){
    23                 if(!vis[i] && num >= a[i]){
    24                     vis[i] = 1;
    25                     num++;
    26                     cnt--;
    27                 }
    28             }
    29         }
    30         flag = !flag;
    31         if(cnt > 0)
    32             ans++;
    33     }
    34     cout << ans << endl;
    35 
    36     return 0;
    37 }

    C - GCD Table(CF-583C)

    给你一个打乱了的GCD表,问是哪些值构成的。

    思路:这n个数一定就是对角线上的数,直接降序排列然后暴力找,每次找到的最大的数一定是其中一个数,然后求出它与已经求出的所有数的gcd在队列中去掉两个这个gcd数,保证所有大于等于下一个数字的gcd一定都被去掉了,剩下的最大的又是要找的数。

    额外定义

    template<typename T>
    using maxHeap = priority_queue<T, vector<T>, less<T> >;

    template<typename T>
    inline T gcd(T a, T b){ return b==0 ? a : gcd(b,a%b); }

    代码

     1 int main(){
     2     ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0);
     3     int n,k = 0,temp,num;
     4     int a[250050],b[250050];
     5     cin>>n;
     6     GOE(i,1,n*n){
     7         cin>>a[i];
     8     }
     9     sort(a+1,a+1+n*n);
    10     maxHeap<int> q;
    11     OG(i,n*n,0){
    12         if(!q.empty())
    13             temp = q.top();
    14         else
    15             temp = 0;
    16         if(a[i] == temp){
    17             q.pop();
    18             continue;
    19         }
    20         GO(j,0,k){
    21             num = gcd(b[j],a[i]);
    22             q.push(num);
    23             q.push(num);
    24         }
    25         b[k++] = a[i];
    26     }
    27     GO(i,0,k)
    28         cout << b[i] << " ";
    29     cout << endl;
    30     
    31     return 0;
    32 }

    F - Calculating Function(CF-486A)

    题意就是按照他给的公式输出F(n);

    思路:可以推出n为偶数是F(n) = n/2,否则F(n) = n/2 - n;

    代码

     1 int main(){
     2     ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0);
     3     ll n;
     4     cin>>n;
     5     if (n&1)
     6         cout << n/2 - n << endl;
     7     else
     8         cout << n/2 << endl;
     9 
    10     return 0;
    11 }

    G - OR in Matrix(CF-486B)

    题目就是说bij为i行和j列的值OR操作的结果,现在给你操作后的表,要你求操作前的表。

    思路:如果bij = 0,则证明i行和j列全是0,如果是1,则证明i行和j列必须有一个1,所以先把所有值设为1,按照题目把某些行列变为0,再判断一遍是否满足题意即可

    代码

     1 int main(){
     2     ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0);
     3     int n,m;
     4     int a[105][105],b[105][105];
     5     fill(b[0],b[0]+105*105,1);
     6     cin>>n>>m;
     7     GOE(i,1,n){
     8         GOE(j,1,m){
     9             cin>>a[i][j];
    10             if(a[i][j] == 0){
    11                 GOE(ii,1,n)
    12                     b[ii][j] = 0;
    13                 GOE(jj,1,m)
    14                     b[i][jj] = 0;
    15             }
    16         }
    17     }
    18 
    19     GOE(i,1,n){
    20         GOE(j,1,m){
    21             if(a[i][j] == 1){
    22                 int flag = 0;
    23                 GOE(ii,1,n){
    24                     if(b[ii][j] == 1){
    25                         flag = 1;
    26                         break;
    27                     }
    28                 }
    29                 GOE(jj,1,m){
    30                     if(b[i][jj] == 1){
    31                         flag = 1;
    32                         break;
    33                     }
    34                 }
    35                 if(!flag){
    36                     cout << "NO" << endl;
    37                     exit(0);
    38                 }
    39             }
    40         }
    41     }
    42 
    43     cout << "YES" << endl;
    44     GOE(i,1,n){
    45         GOE(j,1,m)
    46             cout << b[i][j] << " ";
    47         cout << endl;
    48     }
    49 
    50     return 0;
    51 }

    H - Palindrome Transformation(CF-486C)

    题意就是4种操作,最开始在k位置操作,问最少操作多少次使得原串变成回文串。

    思路:因为是对称的,我们先不要管最开始在哪个位置,遍历即可,当a[i] != a[n-i-1]时候,我们再想是变a[i]还是变另一个,然后答案加上这个值。同时往容器中加上从k走到i远还是走到n-i-1近。

    最后排序,答案加上最远距离于最近距离之差再加上这两者距离k最近的距离即可。

    为什么只需要不需要管k的位置,因为k无论在哪里,我们都需要把所有不符合的字符走到,所以这里得花掉最远距离和最近距离的差,同时我们最开始在k,需要走到最近的位置开始遍历上一段距离,所以最终答案就是

      ans = 每个不合格字符的操作次数 + 不合格字符的区间长度 + 从k位置走到这个区间的某一端点的距离;

    因为不管你的k是否在这个区间内,都需要遍历一遍这个区间。

     1 int main(){
     2     ios_base::sync_with_stdio(false), cout.tie(0), cin.tie(0);
     3     int n,k;
     4     string s;
     5     vector<int> q;
     6     cin>>n>>k>>s;
     7     int len = n/2,ans = 0;
     8     GO(i,0,len){
     9         if(s[i] != s[n-1-i]){
    10             int tp = abs(s[i] - s[n-1-i]);
    11             tp = min(tp,26-tp);
    12             ans += tp;
    13             if(tp)
    14                 q.PB((abs(i+1-k) < abs(n-i-k)) ? i+1 : n-i);
    15         }
    16     }
    17     int cnt = q.size();
    18     if(q.empty())
    19         cout << ans << endl;
    20     else{
    21         sort(q.begin(),q.end());
    22         ans += q[cnt-1] - q[0] + min(abs(q[cnt-1]-k),abs(q[0]-k));
    23         cout << ans << endl;
    24     }
    25     return 0;
    26 }

    D题E题时间关系暂时不补了。

  • 相关阅读:
    Grub 和 UEFI启动
    神舟战神插上耳机没有声音,重启又有声音..
    批处理 ------ @、ECHO OFF、ECHO ON 的使用
    linux command ------ find
    Adobe Premiere Pro CC ------ 快捷键
    分布式session一致性问题
    DNS域名解析
    CDN内容分发
    令牌桶限流算法和漏桶限流算法区别
    AOP与IOC区别
  • 原文地址:https://www.cnblogs.com/xenny/p/9689670.html
Copyright © 2011-2022 走看看