zoukankan      html  css  js  c++  java
  • HIT ACM 2018春 week2 codeforces.com/gym/101652 题解

    A

    题意:判断一个字符串是否存在偶数长度回文子串。

    思路:判断是否有两个字符相等即可。O(n)。

     1 #include <iostream>
     2 #include <fstream>
     3 #include <sstream>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <string>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <queue>
    11 #include <stack>
    12 #include <vector>
    13 #include <set>
    14 #include <map>
    15 #include <list>
    16 #include <iomanip>
    17 #include <cctype>
    18 #include <cassert>
    19 #include <bitset>
    20 #include <ctime>
    21 
    22 using namespace std;
    23 
    24 #define pau system("pause")
    25 #define ll long long
    26 #define pii pair<int, int>
    27 #define pb push_back
    28 #define mp make_pair
    29 #define clr(a, x) memset(a, x, sizeof(a))
    30 
    31 const double pi = acos(-1.0);
    32 const int INF = 0x3f3f3f3f;
    33 const int MOD = 1e9 + 7;
    34 const double EPS = 1e-9;
    35 
    36 /*
    37 #include <ext/pb_ds/assoc_container.hpp>
    38 #include <ext/pb_ds/tree_policy.hpp>
    39 
    40 using namespace __gnu_pbds;
    41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
    42 */
    43 
    44 char s[105];
    45 int main() {
    46     scanf("%s", s + 1);
    47     int l = strlen(s + 1);
    48     for (int i = 1; i < l; ++i) {
    49         if (s[i] == s[i + 1]) {
    50             puts("Or not.");
    51             return 0;
    52         }
    53     }
    54     puts("Odd.");
    55     return 0;
    56 }
    View Code

    B

    题意:总共n种字符,判断一个n*n的方格

    (1)是否每行都包含n种字符,每一列是否都包含n种字符;

    (2)在满足性质(1)的情况下判断第一行和第一列元素是否严格上升

    思路:按上述题意模拟即可。

     1 #include <iostream>
     2 #include <fstream>
     3 #include <sstream>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <string>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <queue>
    11 #include <stack>
    12 #include <vector>
    13 #include <set>
    14 #include <map>
    15 #include <list>
    16 #include <iomanip>
    17 #include <cctype>
    18 #include <cassert>
    19 #include <bitset>
    20 #include <ctime>
    21 
    22 using namespace std;
    23 
    24 #define pau system("pause")
    25 #define ll long long
    26 #define pii pair<int, int>
    27 #define pb push_back
    28 #define mp make_pair
    29 #define clr(a, x) memset(a, x, sizeof(a))
    30 
    31 const double pi = acos(-1.0);
    32 const int INF = 0x3f3f3f3f;
    33 const int MOD = 1e9 + 7;
    34 const double EPS = 1e-9;
    35 
    36 /*
    37 #include <ext/pb_ds/assoc_container.hpp>
    38 #include <ext/pb_ds/tree_policy.hpp>
    39 
    40 using namespace __gnu_pbds;
    41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
    42 */
    43 
    44 int n;
    45 char s[41][41];
    46 set<char> ss;
    47 int main() {
    48     while (~scanf("%d", &n)) {
    49         int flag = 0;
    50         for (int i = 1; i <= n; ++i) {
    51             scanf("%s", s[i] + 1);
    52         }
    53         for (int i = 1; i <= n; ++i) {
    54             ss.clear();
    55             for (int j = 1; j <= n; ++j) {
    56                 ss.insert(s[i][j]);
    57             }
    58             if (n != ss.size()) {
    59                 puts("No");
    60                 flag = 1;
    61                 break;
    62             }
    63         }
    64         if (flag) continue;
    65         for (int j = 1; j <= n; ++j) {
    66             ss.clear();
    67             for (int i = 1; i <= n; ++i) {
    68                 ss.insert(s[i][j]);
    69             }
    70             if (n != ss.size()) {
    71                 puts("No");
    72                 flag = 1;
    73                 break;
    74             }
    75         }
    76         if (flag) continue;
    77         for (int i = 2; i <= n; ++i) {
    78             if (s[i][1] < s[i - 1][1]) {
    79                 puts("Not Reduced");
    80                 flag = 1;
    81                 break;
    82             }
    83         }
    84         if (flag) continue;
    85         for (int j = 2; j <= n; ++j) {
    86             if (s[1][j] < s[1][j - 1]) {
    87                 puts("Not Reduced");
    88                 flag = 1;
    89                 break;
    90             }
    91         }
    92         if (flag) continue;
    93         puts("Reduced");
    94     }
    95     return 0;
    96 }
    View Code

    C

    题意:定义f(x)为x的约数个数,求SUM(f(x))  (a <= x <= b)

    思路:枚举小于等于1e6的因子,对于每一个因子y, a 到 b之间能整出y的个数为 b/y(向下取整) - a/y(向上取整)+ 1,a 到 b 之间能整除y之后剩的因子为 b/y(向下取整), ..., a/y(向上取整)的公差为-1的等差数列。

    因此,在最终答案中直接加上y的个数 * y 以及除y后剩的因子和即可。但为了保证每个y只被算一次,我们应该让除y后剩余间的左端点l = max(a/y(向上取整), y)。同时,在y == l时,不要加两次y。计算量为1e6.

    没理解的话可以结合代码思考,感觉代码比文字表达更清晰。

     1 #include <iostream>
     2 #include <fstream>
     3 #include <sstream>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <string>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <queue>
    11 #include <stack>
    12 #include <vector>
    13 #include <set>
    14 #include <map>
    15 #include <list>
    16 #include <iomanip>
    17 #include <cctype>
    18 #include <cassert>
    19 #include <bitset>
    20 #include <ctime>
    21 
    22 using namespace std;
    23 
    24 #define pau system("pause")
    25 #define ll long long
    26 #define pii pair<int, int>
    27 #define pb push_back
    28 #define mp make_pair
    29 #define clr(a, x) memset(a, x, sizeof(a))
    30 
    31 const double pi = acos(-1.0);
    32 const int INF = 0x3f3f3f3f;
    33 const int MOD = 1e9 + 7;
    34 const double EPS = 1e-9;
    35 
    36 /*
    37 #include <ext/pb_ds/assoc_container.hpp>
    38 #include <ext/pb_ds/tree_policy.hpp>
    39 
    40 using namespace __gnu_pbds;
    41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
    42 */
    43 
    44 ll a, b, ans;
    45 int main() {
    46     scanf("%lld%lld", &a, &b);
    47     for (ll i = 1; i <= 1000000; ++i) {
    48         ll x1 = (a - 1) / i + 1;
    49         ll x2 = b / i;
    50         if (x1 < i) x1 = i;
    51         //printf("%lld %lld %lld
    ", i, x1, x2);
    52         if (i > b) break;
    53         if (x1 > x2) continue;
    54         if (x1 == i) ans -= x1;
    55         ans += (x2 - x1 + 1) * i;
    56         ans += (x2 - x1 + 1) * (x2 + x1) >> 1;
    57     }
    58     printf("%lld", ans);
    59     return 0;
    60 }
    View Code

    D

    题意:定义一个序列 1, 1, 1, 1, 1, 1, ..., 2, 2, 2, 2, 2, 2, .....i, i, i, i, i,  ..., n - 1 (每个数i连续出现n - i次), 求序列中间的那个数。

    思路:对于每个数i,第一次出现的位置都可以O(1)求出来(等差数列求和),我们又可以求出序列总元素个数以及中间数的位置,因此二分判定就好了。O(logn)。

     1 #include <iostream>
     2 #include <fstream>
     3 #include <sstream>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <string>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <queue>
    11 #include <stack>
    12 #include <vector>
    13 #include <set>
    14 #include <map>
    15 #include <list>
    16 #include <iomanip>
    17 #include <cctype>
    18 #include <cassert>
    19 #include <bitset>
    20 #include <ctime>
    21 
    22 using namespace std;
    23 
    24 #define pau system("pause")
    25 #define ll long long
    26 #define pii pair<int, int>
    27 #define pb push_back
    28 #define mp make_pair
    29 #define clr(a, x) memset(a, x, sizeof(a))
    30 
    31 const double pi = acos(-1.0);
    32 const int INF = 0x3f3f3f3f;
    33 const int MOD = 1e9 + 7;
    34 const double EPS = 1e-9;
    35 
    36 /*
    37 #include <ext/pb_ds/assoc_container.hpp>
    38 #include <ext/pb_ds/tree_policy.hpp>
    39 
    40 using namespace __gnu_pbds;
    41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
    42 */
    43 
    44 ll n;
    45 ll cal(ll x) {
    46     return (n + n - 1 - x) * x >> 1;
    47 }
    48 int main() {
    49     scanf("%lld", &n);
    50     ll cnt = ((n * (n - 1) >> 1) + 1) >> 1;
    51     ll ans = 0, s = 0, e = n, mi;
    52     while (s <= e) {
    53         mi = s + e >> 1;
    54         if (cal(mi) < cnt) {
    55             s = (ans = mi) + 1;
    56         } else {
    57             e = mi - 1;
    58         }
    59     }
    60     printf("%lld", ans + 1);
    61     return 0;
    62 }
    View Code

    E

    题意:已知一个机器人的速度,起点终点都在x轴方向,中间有一些竖向的传送带,各个速度都已知, 判定一下机器人到终点的最短时间。

    思路:对y轴移动距离列方程,把机器人速度分解,vy * L / vx = SUM(vi * li / vx)。vx可以约掉。因此马上求出vy, vx也可以求出。复杂度O(n)。

     1 #include <iostream>
     2 #include <fstream>
     3 #include <sstream>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <string>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <queue>
    11 #include <stack>
    12 #include <vector>
    13 #include <set>
    14 #include <map>
    15 #include <list>
    16 #include <iomanip>
    17 #include <cctype>
    18 #include <cassert>
    19 #include <bitset>
    20 #include <ctime>
    21 
    22 using namespace std;
    23 
    24 #define pau system("pause")
    25 #define ll long long
    26 #define pii pair<int, int>
    27 #define pb push_back
    28 #define mp make_pair
    29 #define clr(a, x) memset(a, x, sizeof(a))
    30 
    31 const double pi = acos(-1.0);
    32 const int INF = 0x3f3f3f3f;
    33 const int MOD = 1e9 + 7;
    34 const double EPS = 1e-9;
    35 
    36 /*
    37 #include <ext/pb_ds/assoc_container.hpp>
    38 #include <ext/pb_ds/tree_policy.hpp>
    39 
    40 using namespace __gnu_pbds;
    41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
    42 */
    43 
    44 int n;
    45 double x, V, v[105], l[105], r[105];
    46 int main() {
    47     double cnt = 0;
    48     scanf("%d%lf%lf", &n, &x, &V);
    49     for (int i = 1; i <= n; ++i) {
    50         scanf("%lf%lf%lf", &l[i], &r[i], &v[i]);
    51         cnt += (r[i] - l[i]) * v[i];
    52     }
    53     double vy = fabs(cnt / x);
    54     if (vy >= V) {
    55         puts("Too hard");
    56         return 0;
    57     } else {
    58         double vx = sqrt(V * V - vy * vy);
    59         if (vx * 2 <= V + EPS) {
    60             puts("Too hard");
    61         } else {
    62             printf("%.3f
    ", x / vx);
    63         }
    64     }
    65     return 0;
    66 }
    View Code

    F

    题意:对于一个只有RB两种字符的字符串,求出一个子串使得‘R’, ‘B’两种字符数量的差值最大。

    思路:可以将问题拆开。一种是求R的数量-B的数量最多,另一个是B的数量-R的数量最大。考虑每个单独的问题,比如要求R-B尽可能多,我们线性扫一遍,如果当前R的数量大于等于B,那么我们遇见R就加1, 遇见B就减1。

    如果R比B少,那么我们为了使这个差值尽可能大,显然要舍弃之前选的那段序列,而从当前位置重新开始取。复杂度O(n)。

     1 #include <iostream>
     2 #include <fstream>
     3 #include <sstream>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <string>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <queue>
    11 #include <stack>
    12 #include <vector>
    13 #include <set>
    14 #include <map>
    15 #include <list>
    16 #include <iomanip>
    17 #include <cctype>
    18 #include <cassert>
    19 #include <bitset>
    20 #include <ctime>
    21 
    22 using namespace std;
    23 
    24 #define pau system("pause")
    25 #define ll long long
    26 #define pii pair<int, int>
    27 #define pb push_back
    28 #define mp make_pair
    29 #define clr(a, x) memset(a, x, sizeof(a))
    30 
    31 const double pi = acos(-1.0);
    32 const int INF = 0x3f3f3f3f;
    33 const int MOD = 1e9 + 7;
    34 const double EPS = 1e-9;
    35 
    36 /*
    37 #include <ext/pb_ds/assoc_container.hpp>
    38 #include <ext/pb_ds/tree_policy.hpp>
    39 
    40 using namespace __gnu_pbds;
    41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
    42 */
    43 
    44 int n;
    45 char s[100015];
    46 void solve(int &ma, int &l1, int &r1, char c) {
    47     for (int i = 1, j = 1, cnt = 0, flag = 1; j <= n; ++j) {
    48         if (!cnt) {
    49             if (c == s[j]) {
    50                 ++cnt;
    51                 if (cnt > ma) {
    52                     l1 = r1 = j;
    53                     ma = cnt;
    54                 }
    55                 if (flag) {
    56                     i = j;
    57                     flag = 0;
    58                 }
    59             } else {
    60                 flag = 1;
    61                 continue;
    62             }
    63         } else {
    64             if (c == s[j]) {
    65                 ++cnt;
    66                 if (cnt > ma) {
    67                     r1 = j;
    68                     l1 = i;
    69                     ma = cnt;
    70                 }
    71             } else {
    72                 --cnt;
    73             }
    74         }
    75     }
    76 }
    77 int main() {
    78     scanf("%s", s + 1);
    79     n = strlen(s + 1);
    80     int ma1 = 0, l1 = 0, r1 = 0, ma2 = 0, l2 = 0, r2 = 0;
    81     solve(ma1, l1, r1, 'B');
    82     solve(ma2, l2, r2, 'R');
    83     int ans_l, ans_r;
    84     if (ma1 > ma2 || (ma1 == ma2 && (l1 < l2 || (l1 == l2 && r1 < r2)))) {
    85         ans_l = l1, ans_r = r1;
    86     } else {
    87         ans_l = l2, ans_r = r2;
    88     }
    89     printf("%d %d", ans_l, ans_r);
    90     return 0;
    91 }
    View Code

    G

    题意:一个有向图中每条边都有一段区间,表示权限,只有x在这段区间内才可以经过这条边,求出所有能从起点走到终点的x。

    思路:我们把所有的区间统一改成左闭右开的形式。把所有的时间段的端点提取出来并从小到大排序。然后考虑每个时间点ti,如果ti能从起点到达终点,那么[t(i), t(i + 1))这段区间内的所有时间点都可以到达终点,因为如果t(i)可以到达终点,那么它肯定不能只是一个时间段的右开端点,所以他至少是一个左闭端点,因此其向后取的那一小段时间段一定可取;如果t(i)不能到达,则显然只是一个右开端点,因此不取它后面的一段区间。O(mlogm + m*(m + n))。

     1 #include <iostream>
     2 #include <fstream>
     3 #include <sstream>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <string>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <queue>
    11 #include <stack>
    12 #include <vector>
    13 #include <set>
    14 #include <map>
    15 #include <list>
    16 #include <iomanip>
    17 #include <cctype>
    18 #include <cassert>
    19 #include <bitset>
    20 #include <ctime>
    21 
    22 using namespace std;
    23 
    24 #define pau system("pause")
    25 #define ll long long
    26 #define pii pair<int, int>
    27 #define pb push_back
    28 #define mp make_pair
    29 #define clr(a, x) memset(a, x, sizeof(a))
    30 
    31 const double pi = acos(-1.0);
    32 const int INF = 0x3f3f3f3f;
    33 const int MOD = 1e9 + 7;
    34 const double EPS = 1e-9;
    35 
    36 /*
    37 #include <ext/pb_ds/assoc_container.hpp>
    38 #include <ext/pb_ds/tree_policy.hpp>
    39 
    40 using namespace __gnu_pbds;
    41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
    42 */
    43 
    44 int n, m, k, s, t, ans;
    45 struct edge {
    46     int v, l, r;
    47     edge () {}
    48     edge (int v, int l, int r) : v(v), l(l), r(r) {}
    49 };
    50 vector<edge> E[1015];
    51 vector<int> timestamps;
    52 bool visit[1015];
    53 void dfs(int x, int timestamp) {
    54     visit[x] = true;
    55     for (int i = 0; i < E[x].size(); ++i) {
    56         int v = E[x][i].v;
    57         int l = E[x][i].l;
    58         int r = E[x][i].r;
    59         if (l <= timestamp && timestamp <= r && !visit[v]) {
    60             dfs(v, timestamp);
    61         }
    62     }
    63 }
    64 int main() {
    65     scanf("%d%d%d%d%d", &n, &m, &k, &s, &t);
    66     while (m--) {
    67         int a, b, c, d;
    68         scanf("%d%d%d%d", &a, &b, &c, &d);
    69         E[a].pb(edge(b, c, d));
    70         timestamps.pb(c);
    71         timestamps.pb(d + 1);
    72     }
    73     sort(timestamps.begin(), timestamps.end());
    74     int number_Of_Timestamps = unique(timestamps.begin(), timestamps.end()) - timestamps.begin();
    75     for (int i = 0; i < number_Of_Timestamps - 1; ++i) {
    76         int timestamp = timestamps[i];
    77         clr(visit, false);
    78         dfs(s, timestamp);
    79         if (visit[t]) {
    80             ans += timestamps[i + 1] - timestamps[i];
    81         }
    82     }
    83     printf("%d", ans);
    84     return 0;
    85 }
    View Code

    H

    题意:改变一个不均匀骰子的一个面的点数(可以为实数),使得其期望为3.5

    思路:求出期望差值,除以概率最大的那个面就是改变的最小值。

     1 #include <iostream>
     2 #include <fstream>
     3 #include <sstream>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <string>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <queue>
    11 #include <stack>
    12 #include <vector>
    13 #include <set>
    14 #include <map>
    15 #include <list>
    16 #include <iomanip>
    17 #include <cctype>
    18 #include <cassert>
    19 #include <bitset>
    20 #include <ctime>
    21 
    22 using namespace std;
    23 
    24 #define pau system("pause")
    25 #define ll long long
    26 #define pii pair<int, int>
    27 #define pb push_back
    28 #define mp make_pair
    29 #define clr(a, x) memset(a, x, sizeof(a))
    30 
    31 const double pi = acos(-1.0);
    32 const int INF = 0x3f3f3f3f;
    33 const int MOD = 1e9 + 7;
    34 const double EPS = 1e-9;
    35 
    36 /*
    37 #include <ext/pb_ds/assoc_container.hpp>
    38 #include <ext/pb_ds/tree_policy.hpp>
    39 
    40 using namespace __gnu_pbds;
    41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
    42 */
    43 
    44 double p[11], sum, ma;
    45 int main() {
    46     for (int i = 1; i <= 6; ++i) {
    47         scanf("%lf", &p[i]);
    48         sum += p[i] * i;
    49         ma = max(ma, p[i]);
    50     }
    51     printf("%.3f", fabs(sum - 3.5) / ma);
    52     return 0;
    53 }
    View Code

    I

    题意:一个无限长字符串上一系列插入删除操作,问两组操作是否等价。

    思路:用个链表暴力n*n模拟?(这题我还没写,这几天写完更新)

    UPDATE:

    思路一:

      确实是个链表模拟的n * n暴力,但比较麻烦。我的做法是链表上每个节点存一下到下一个节点的距离(距离定义为当前节点到下一个节点的左开右闭区间内字符个数),以及节点的虚实信息(虚节点定义为存在于最初串中并在之后被删除的元素,即遇见此类删除最初元素的情况,我们在链表中加入一个虚节点;实节点定义为之后插入的新元素;如果插入且之后被删除则我们不存储这类节点,在其被删除的时候也将该实节点从链表中删除)。至此,链表插入删除维护完毕。

      但这样处理会产生问题,即等价的一系列操作会产生不同形式的最终链表(例子在代码最后的注释里)。因此我们在判断之前要对其进行统一化处理,格式之所以不统一是因为有一些地方可以合并但没有合并,所以我们合并所有能合并的地方(再次声明距离的定义是左开右闭区间内字符数量):(1)当前节点为虚节点,且距离下一节点为0,显然可以删掉(2)当前节点为实节点,且前一个节点为虚节点且距当前节点距离1,此时我们应删除前一个节点,并让新产生的前一个节点距离加1(3)其他所有情况都代表着两个节点之间有原序列中的元素,皆不可合并。

      最后严格地判断两个链表中对应节点是否完全相等即可。

      1 #include <iostream>
      2 #include <fstream>
      3 #include <sstream>
      4 #include <cstdlib>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <string>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <queue>
     11 #include <stack>
     12 #include <vector>
     13 #include <set>
     14 #include <map>
     15 #include <list>
     16 #include <iomanip>
     17 #include <cctype>
     18 #include <cassert>
     19 #include <bitset>
     20 #include <ctime>
     21 
     22 using namespace std;
     23 
     24 #define pau system("pause")
     25 #define ll long long
     26 #define pii pair<int, int>
     27 #define pb push_back
     28 #define mp make_pair
     29 #define clr(a, x) memset(a, x, sizeof(a))
     30 
     31 const double pi = acos(-1.0);
     32 const int INF = 0x3f3f3f3f;
     33 const int MOD = 1e9 + 7;
     34 const double EPS = 1e-9;
     35 
     36 /*
     37 #include <ext/pb_ds/assoc_container.hpp>
     38 #include <ext/pb_ds/tree_policy.hpp>
     39 
     40 using namespace __gnu_pbds;
     41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
     42 */
     43 
     44 struct node {
     45     ll l;
     46     bool is_real;
     47     char c;
     48     node () {}
     49     node (ll l, bool is_real, char c) : l(l), is_real(is_real), c(c) {}
     50     bool operator != (const node &tnode) const {
     51         return l != tnode.l || is_real != tnode.is_real || c != tnode.c;}
     52 };
     53 list<node> l1, l2;
     54 void ini() {
     55     l1.insert(l1.begin(), node(1e17, true, '#'));
     56     l1.insert(l1.end(), node(1e17, true, '#'));
     57     l2.insert(l2.begin(), node(1e17, true, '#'));
     58     l2.insert(l2.end(), node(1e17, true, '#'));
     59 }
     60 void Insert(list<node> &l) {
     61     ll p;
     62     char c;
     63     scanf("%lld %c", &p, &c);
     64     list<node>::iterator it = l.begin();
     65     ll cnt = 0;
     66     while (it != l.end()) {
     67         if (p > cnt + (*it).l) {
     68             cnt += (*it).l;
     69             ++it;
     70         } else {
     71             ll len = (*it).l;
     72             (*it).l = p - cnt;
     73             l.insert(++it, node(len + 1 - (p - cnt), true, c));
     74             break;
     75         }
     76     }
     77     /*for (list<node>::iterator it = l.begin(); it != l.end(); ++it) {
     78         printf("len1 = %lld, is_real1 = %d, c1 = %c
    ", (*it).l, (*it).is_real, (*it).c);
     79     }*/
     80 }
     81 void Delete(list<node> &l) {
     82     ll p;
     83     scanf("%lld", &p);
     84     list<node>::iterator it = l.begin();
     85     ll cnt = 0;
     86     while (it != l.end()) {
     87         if (p > cnt + (*it).l) {
     88             cnt += (*it).l;
     89             ++it;
     90         } else {
     91             ll len = (*it).l;
     92             (*it).l = p - cnt - 1;
     93             list<node>::iterator it1 = ++it;
     94             --it;
     95 
     96             if (l.end() == it1 || p < cnt + len || (p == cnt + len && !(*it1).is_real)) {
     97                 l.insert(it1, node(len - (p - cnt), false, '#'));
     98             } else {
     99                 ll len2 = (*it1).l;
    100                 (*it).l += len2;
    101                 l.erase(it1);
    102             }
    103             break;
    104         }
    105     }
    106     /*for (list<node>::iterator it = l.begin(); it != l.end(); ++it) {
    107         printf("len1 = %lld, is_real1 = %d, c1 = %c
    ", (*it).l, (*it).is_real, (*it).c);
    108     }*/
    109 }
    110 void modify(list<node> &l) {
    111     for (list<node>::iterator it = l.begin(); it != l.end(); ) {
    112         if (0 == (*it).l && !(*it).is_real) {
    113             it = l.erase(it);
    114         } else {
    115             if ((*it).is_real) {
    116                 list<node>::iterator it1 = it;
    117                 --it1;
    118                 if (1 == (*it1).l && !(*it1).is_real) {
    119                     it1 = l.erase(it1);
    120                     --it1;
    121                     ++(*it1).l;
    122                 }
    123             }
    124             ++it;
    125         }
    126     }
    127 }
    128 bool Equal() {
    129 
    130     modify(l1);
    131     modify(l2);
    132 
    133     if (l1.size() != l2.size()) return false;
    134 
    135     list<node>::iterator it1 = l1.begin();
    136     list<node>::iterator it2 = l2.begin();
    137 
    138     for (; it1 != l1.end() && it2 != l2.end(); ) {
    139         //printf("len1 = %lld, is_real1 = %d, c1 = %c
    ", (*it1).l, (*it1).is_real, (*it1).c);
    140         //printf("len2 = %lld, is_real2 = %d, c2 = %c
    ", (*it2).l, (*it2).is_real, (*it2).c);
    141 
    142         if (*it1 != *it2) return false;
    143 
    144         ++it1, ++it2;
    145     }
    146 
    147     return true;;
    148 }
    149 void solve(list<node> &l) {
    150     char op;
    151     while (scanf(" %c", &op) && 'E' != op) {
    152         if ('I' == op) {
    153             Insert(l);
    154         } else {
    155             Delete(l);
    156         }
    157     }
    158 }
    159 int main() {
    160     ini();
    161     solve(l1);
    162     solve(l2);
    163     puts(Equal() ? "0" : "1");
    164     return 0;
    165 }
    166 /*
    167 I 3 x
    168 D 5
    169 D 4
    170 D 2
    171 D 1
    172 E
    173 I 1 x
    174 D 2
    175 D 2
    176 D 2
    177 D 2
    178 E
    179 */
    View Code

    思路二:

    官方题解的做法,就是不用链表模拟,将所有的操作都统一成D i1, i2, ..., in, I j1, j2, ..., jm 的形式,其中i序列递减,j序列递增。类似冒泡排序按五类情况模拟即可。

    J

    题意:一个n * m的方格上有‘B’, 'R', '.'分别表示黑色,红色,以及目前为空着。要求每个B左上角的所有块都必须为黑色,R右下角的所有块都必须为红色。

    思路:你可以先n*n*m*m暴力利用所有已知的R,B信息把方格填充,这样左上角以及右下角都被确定,待处理的只有中间空的一部分,这个中间部分满足列数从左到右时,其相应待确定的行数单调递减。

    因此,我们用dp[j][i]表示第j列第i行为此列最后一个黑色块,那么dp[j][i] = SUM(dp[j - 1][k]),其中k从i到n。复杂度O(n * n * m * m),可以优化到O(n*m)。

      1 #include <iostream>
      2 #include <fstream>
      3 #include <sstream>
      4 #include <cstdlib>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <string>
      8 #include <cstring>
      9 #include <algorithm>
     10 #include <queue>
     11 #include <stack>
     12 #include <vector>
     13 #include <set>
     14 #include <map>
     15 #include <list>
     16 #include <iomanip>
     17 #include <cctype>
     18 #include <cassert>
     19 #include <bitset>
     20 #include <ctime>
     21 
     22 using namespace std;
     23 
     24 #define pau system("pause")
     25 #define ll long long
     26 #define pii pair<int, int>
     27 #define pb push_back
     28 #define mp make_pair
     29 #define clr(a, x) memset(a, x, sizeof(a))
     30 
     31 const double pi = acos(-1.0);
     32 const int INF = 0x3f3f3f3f;
     33 const int MOD = 1e9 + 7;
     34 const double EPS = 1e-9;
     35 
     36 /*
     37 #include <ext/pb_ds/assoc_container.hpp>
     38 #include <ext/pb_ds/tree_policy.hpp>
     39 
     40 using namespace __gnu_pbds;
     41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
     42 */
     43 
     44 int n, m;
     45 char mmp[35][35];
     46 ll dp[35][35];
     47 
     48 int main() {
     49     scanf("%d%d", &n, &m);
     50     for (int i = 1; i <= n; ++i) {
     51         scanf("%s", mmp[i] + 1);
     52     }
     53     for (int i = 1; i <= n; ++i) {
     54         for (int j = 1; j <= m; ++j) {
     55             if ('B' == mmp[i][j]) {
     56                 for (int k = 1; k <= i; ++k) {
     57                     for (int l = 1; l <= j; ++l) {
     58                         if ('R' == mmp[k][l]) {
     59                             puts("0");
     60                             return 0;
     61                         }
     62                         mmp[k][l] = 'B';
     63                     }
     64                 }
     65             }
     66             if ('R' == mmp[i][j]) {
     67                 for (int k = i; k <= n; ++k) {
     68                     for (int l = j; l <= m; ++l) {
     69                         if ('B' == mmp[k][l]) {
     70                             puts("0");
     71                             return 0;
     72                         }
     73                         mmp[k][l] = 'R';
     74                     }
     75                 }
     76             }
     77         }
     78     }
     79     for (int i = n; ~i; --i) {
     80         if ('R' == mmp[i][1]) continue;
     81         dp[i][1] = 1;
     82         if ('B' == mmp[i][1]) break;
     83     }
     84     for (int j = 2; j <= m; ++j) {
     85         for (int i = n; ~i; --i) {
     86             if ('R' == mmp[i][j]) continue;
     87             for (int k = i; k <= n; ++k) {
     88                 dp[i][j] += dp[k][j - 1];
     89             }
     90             if ('B' == mmp[i][j]) break;
     91         }
     92     }
     93     /*for (int i = 0; i <= n; ++i) {
     94         for (int j = 1; j <= m; ++j) {
     95             printf("%d ", dp[i][j]);
     96         }
     97         puts("");
     98     }*/
     99     ll ans = 0;
    100     for (int i = 0; i <= n; ++i) {
    101         ans += dp[i][m];
    102     }
    103     printf("%lld", ans);
    104     return 0;
    105 }
    View Code

    K

    题意:美国国旗是有s个星,所有奇数行星数都为x, 所有偶数行星数都为y, x等于y或y + 1。

    思路:枚举三种情况,(1) x == y (2) x == y + 1总行数为偶数 (3) x == y + 1总行数为奇数。最后排下序,复杂度O(S + sqrt(s) * logs)。

     1 #include <iostream>
     2 #include <fstream>
     3 #include <sstream>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <string>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <queue>
    11 #include <stack>
    12 #include <vector>
    13 #include <set>
    14 #include <map>
    15 #include <list>
    16 #include <iomanip>
    17 #include <cctype>
    18 #include <cassert>
    19 #include <bitset>
    20 #include <ctime>
    21 
    22 using namespace std;
    23 
    24 #define pau system("pause")
    25 #define ll long long
    26 #define pii pair<int, int>
    27 #define pb push_back
    28 #define mp make_pair
    29 #define clr(a, x) memset(a, x, sizeof(a))
    30 
    31 const double pi = acos(-1.0);
    32 const int INF = 0x3f3f3f3f;
    33 const int MOD = 1e9 + 7;
    34 const double EPS = 1e-9;
    35 
    36 /*
    37 #include <ext/pb_ds/assoc_container.hpp>
    38 #include <ext/pb_ds/tree_policy.hpp>
    39 
    40 using namespace __gnu_pbds;
    41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
    42 */
    43 
    44 set<pii> ss;
    45 int s;
    46 int main() {
    47     scanf("%d", &s);
    48     for (int i = 2; i < s; ++i) {
    49         if (s % i == 0) {
    50             ss.insert(mp(i, i));
    51         }
    52     }
    53     for (int i = 2; i < s; ++i) {
    54         if ((s - i) % (i + i - 1) == 0 || (s % (i + i - 1) == 0) ) {
    55             ss.insert(mp(i, i - 1));
    56         }
    57     }
    58     printf("%d:
    ", s);
    59     for (set<pii>::iterator it = ss.begin(); it != ss.end(); ++it) {
    60         int x = (*it).first, y = (*it).second;
    61         printf("%d,%d
    ", x, y);
    62     }
    63     return 0;
    64 }
    View Code

    L

    题意:已知x, k, p, 求x * n + k * p / n的最小值

    思路:对号函数,因为n为整数,输出sqrt(k * p / x)左右两个整点对应函数值的最小值。O(1)。

     1 #include <iostream>
     2 #include <fstream>
     3 #include <sstream>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <string>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <queue>
    11 #include <stack>
    12 #include <vector>
    13 #include <set>
    14 #include <map>
    15 #include <list>
    16 #include <iomanip>
    17 #include <cctype>
    18 #include <cassert>
    19 #include <bitset>
    20 #include <ctime>
    21 
    22 using namespace std;
    23 
    24 #define pau system("pause")
    25 #define ll long long
    26 #define pii pair<int, int>
    27 #define pb push_back
    28 #define mp make_pair
    29 #define clr(a, x) memset(a, x, sizeof(a))
    30 
    31 const double pi = acos(-1.0);
    32 const int INF = 0x3f3f3f3f;
    33 const int MOD = 1e9 + 7;
    34 const double EPS = 1e-9;
    35 
    36 /*
    37 #include <ext/pb_ds/assoc_container.hpp>
    38 #include <ext/pb_ds/tree_policy.hpp>
    39 
    40 using namespace __gnu_pbds;
    41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
    42 */
    43 
    44 int k, p, x;
    45 double cal(int n) {
    46     return 1.0 * x * n + 1.0 * k * p / n;
    47 }
    48 int main() {
    49     scanf("%d%d%d", &k, &p, &x);
    50     int n = sqrt((k * p + 0.5) / x);
    51     printf("%.3f
    ", min(cal(n), cal(n + 1)));
    52     return 0;
    53 }
    View Code

    M

    题意:给一个n,求出大于n中第一个不含0的数。

    思路:从n+1开始枚举即可,复杂度O(n / 10)。

     1 #include <iostream>
     2 #include <fstream>
     3 #include <sstream>
     4 #include <cstdlib>
     5 #include <cstdio>
     6 #include <cmath>
     7 #include <string>
     8 #include <cstring>
     9 #include <algorithm>
    10 #include <queue>
    11 #include <stack>
    12 #include <vector>
    13 #include <set>
    14 #include <map>
    15 #include <list>
    16 #include <iomanip>
    17 #include <cctype>
    18 #include <cassert>
    19 #include <bitset>
    20 #include <ctime>
    21 
    22 using namespace std;
    23 
    24 #define pau system("pause")
    25 #define ll long long
    26 #define pii pair<int, int>
    27 #define pb push_back
    28 #define mp make_pair
    29 #define clr(a, x) memset(a, x, sizeof(a))
    30 
    31 const double pi = acos(-1.0);
    32 const int INF = 0x3f3f3f3f;
    33 const int MOD = 1e9 + 7;
    34 const double EPS = 1e-9;
    35 
    36 /*
    37 #include <ext/pb_ds/assoc_container.hpp>
    38 #include <ext/pb_ds/tree_policy.hpp>
    39 
    40 using namespace __gnu_pbds;
    41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update> T;
    42 */
    43 
    44 int n;
    45 bool ok(int x) {
    46     while (x) {
    47         if (x % 10 == 0) return false;
    48         x /= 10;
    49     }
    50     return true;
    51 }
    52 int main() {
    53     scanf("%d", &n);
    54     for (int i = n + 1; ; ++i) {
    55         if (ok(i)) {
    56             printf("%d
    ", i);
    57             return 0;
    58         }
    59     }
    60 
    61     return 0;
    62 }
    View Code
  • 相关阅读:
    OpenGL的glTranslatef平移变换函数详解
    OpenGL的glRotatef旋转变换函数详解
    OpenGL的GLUT初始化函数[转]
    OpenGL的GLUT事件处理(Event Processing)窗口管理(Window Management)函数[转]
    OpenGL的GLUT注册回调函数[转]
    OpenGL的gluLookAt和glOrtho的关系
    OpenGL的glClearColor和glClear改变背景颜色
    OpenGL的gluPerspective和gluLookAt的关系[转]
    OpenGL的glOrtho平行投影函数详解[转]
    OpenGL的glViewport视口变换函数详解[转]
  • 原文地址:https://www.cnblogs.com/BIGTOM/p/8544267.html
Copyright © 2011-2022 走看看