zoukankan      html  css  js  c++  java
  • Codeforces Round #215 (Div. 1)

    A Sereja and Algorithm

    题意:给定有x,y,z组成的字符串,每次询问某一段s[l, r]能否变成变成zyxzyx的循环体。

    分析:

    分析每一段x,y,z数目是否满足构成循环体,当然长度<3的要特判。

    代码:

     1 #include <bits/stdc++.h>
     2 #define in freopen("solve_in.txt", "r", stdin);
     3 #define pb push_back
     4 
     5 using namespace std;
     6 typedef long long LL;
     7 
     8 const int maxn = (int)1e5 + 100;
     9 char s[maxn];
    10 int cnt[maxn][3];
    11 int main() {
    12 
    13     int m;
    14     scanf("%s", s+1);
    15     scanf("%d", &m);
    16     int len = strlen(s+1);
    17     for(int i = 1; i <= len; i++) {
    18         for(int k = 0; k < 3; k++)
    19             cnt[i][k] = cnt[i-1][k];
    20         cnt[i][s[i]-'x']++;
    21     }
    22     for(int i = 0; i < m; i++) {
    23         int l, r;
    24         scanf("%d%d", &l, &r);
    25         int a = cnt[r][0]-cnt[l-1][0];
    26         int b = cnt[r][1]-cnt[l-1][1];
    27         int c = cnt[r][2]-cnt[l-1][2];
    28         int tmp = r-l+1;
    29         if(tmp < 3)
    30             puts("YES");
    31         else {
    32 
    33             if(tmp%3 == 0) {
    34                 if(a == b && b == c)
    35                     puts("YES");
    36                 else puts("NO");
    37             } else if(tmp%3 == 1) {
    38                 if((a == b && c - b == 1) || (b == c && a-b == 1) || (a == c &&b -a == 1))
    39                     puts("YES");
    40                 else puts("NO");
    41             } else {
    42                 if((a == b && a-c == 1) || (b == c && b-a==1) || (a == c && a-b == 1))
    43                     puts("YES");
    44                 else puts("NO");
    45             }
    46         }
    47     }
    48     return 0;
    49 }
    View Code

    B Sereja ans Anagrams

    题意:给定2个数组,a[1...n],以及b[1...m]问能否从a中等间隔的选取m个数,使得这m个数与b中各个整数数目对应相等。

    分析:

    容易知道由于是等间隔p的出现,所以可以将a[1..n]的数按间隔分成p组,每次添加一个数时,看相应的组m个数形成的序列是否和b中数的数目对应相等,每次添加,减少一个数,最多改变2个数的数目,看是不是所有的数的数目都满足与在b中的相等。感觉和单调队列类似。

    代码:

     1 #include <bits/stdc++.h>
     2 #define in freopen("solve_in.txt", "r", stdin);
     3 #define pb push_back
     4 
     5 using namespace std;
     6 typedef long long LL;
     7 typedef map<int, int> MPII;
     8 
     9 const int maxn = 2*(int)1e5;
    10 int n, m, p;
    11 MPII mps, mx[maxn];
    12 vector<int> ans;
    13 int a[maxn], b[maxn];
    14 int sat[maxn];
    15 queue<int> q[maxn];
    16 
    17 int main() {
    18     
    19     scanf("%d%d%d", &n, &m, &p);
    20     for(int i = 0; i < n; i++) {
    21         scanf("%d", a+i);
    22     }
    23     int dif = 0;
    24     for(int i = 0; i < m; i++) {
    25         int t;
    26         scanf("%d", &t);
    27         if(mps[t] == 0)
    28             dif++;
    29         mps[t]++;
    30     }
    31     for(int i = 0; i < n; i++) {
    32         int di = i%p;
    33         if(q[di].size() >= m) {
    34             int u = q[di].front();
    35             q[di].pop();
    36             if(mx[di][u] == mps[u])
    37                 sat[di]--;
    38             else if(mx[di][u] == mps[u]+1)
    39                 sat[di]++;
    40             mx[di][u]--;
    41         }
    42         int u = a[i];
    43         q[di].push(a[i]);
    44         if(mx[di][u] == mps[u])
    45             sat[di]--;
    46         else if(mx[di][u] == mps[u]-1)
    47             sat[di]++;
    48         mx[di][u]++;
    49         if(sat[di] == dif)
    50             ans.pb(i-(m-1)*p);
    51     }
    52     cout<<ans.size()<<endl;
    53     for(int i = 0; i < ans.size(); i++) {
    54         printf("%d%c", ans[i]+1, i == ans.size()-1?'
    ':' ');
    55     }
    56     return 0;
    57 }
    View Code

    C Sereja and the Arrangement of Numbers

    题意:n个位置,从m不同的数中选一些数去填充,构成一个数组,数组中出现的任何两个数一定要在数组中至少连续出现一次,每个数都有一个代价,要求选出的数总代价最大!

    分析:首先肯定的是选出代价尽量大的数,那么就要确定n个位置最多放多少个不同的数,做的时候其实是想到了完全图的,但是没继续想下去。由于任何两个数都要相邻出现,所以肯定是满足完全图关系的,但是如果将相邻关系看做一条边的话,n个位置n-1条边,而且这n-1条边是能够从左走到右,也就是构成一个半欧拉图。

    半欧拉图:最多有两个点度数为奇数。对于偶数个节点完全图,每个点度数为奇数,添加一条边能够使得两个点度数变为偶数,所以最少需要添加(点数/2-1)条边构成半欧拉图,因为最终还是允许两个点度数为奇数。奇数个结点完全图,度数为偶数,所以不需要添加边了。

    这样根据,图中n-1条边二分最多能放置的结点数,得到数组中最多出现多少个不同的数,贪心选取最大就行了。

    代码:

     1 #include <bits/stdc++.h>
     2 #define in freopen("solve_in.txt", "r", stdin);
     3 #define pb push_back
     4 
     5 using namespace std;
     6 typedef long long LL;
     7 typedef map<int, int> MPII;
     8 const int maxn = (int)1e5 + 100;
     9 
    10 int w[maxn];
    11 int getAns(int lim, int r){
    12     int l = 1;
    13     while(l < r){
    14         int mid((l+r+1)>>1);
    15         int tmp;
    16         if(mid&1){
    17             tmp = ((LL)mid*(mid-1)>>1);
    18             if(tmp <= lim)
    19                 l = mid;
    20             else r = mid-1;
    21         }
    22         else {
    23             tmp = ((LL)mid*(mid-1)/2+mid/2-1);
    24             if(tmp <= lim)
    25                 l = mid;
    26             else r = mid-1;
    27         }
    28     }
    29     return l;
    30 }
    31 int main(){
    32 
    33     int n, m;
    34     scanf("%d%d", &n, &m);
    35     for(int i(0); i != m; i++){
    36         scanf("%*d%d", w+i);
    37     }
    38     sort(w, w+m, greater<int> ());
    39     n = getAns(n-1, m);
    40     LL ans = 0;
    41     for(int i = 0; i != n; i++)
    42         ans += w[i];
    43     cout<<ans<<endl;
    44     return 0;
    45 }
    View Code
  • 相关阅读:
    线性回归损失函数求解
    【线性代数】四个基本子空间
    【线性代数】如何寻找一个投影矩阵
    【hihoCoder】#1133 : 二分·二分查找之k小数
    [LeetCode解题报告] 502. IPO
    [LeetCode解题报告] 703. 数据流中的第K大元素
    【排序】堆排序
    全文检索以及Lucene的应用
    MySql优化之mycat
    MySql优化之主从复制
  • 原文地址:https://www.cnblogs.com/rootial/p/3958811.html
Copyright © 2011-2022 走看看