• Codeforces Round #333 (Div. 2)


    因为现在太渣了只能做div2;争取每次div2都做出4题,然后提高自己能力之后,再来个5题全过,所以下面只有四题的题解;

    题A

    题意:给你两个数,但是用的是数组来表示,每个数有n个数,然后有一个基数base,也就是base进制的意思,然后问你这两个数那个比较大。

    题解:水题,直接开龙龙模拟

     

     1 /*zhen hao*/
     2 #include <bits/stdc++.h>
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 int val[50];
     7 
     8 int main() {
     9   //freopen("case.in", "r", stdin);
    10   int n, base;
    11   cin >> n >> base;
    12   for (int i = 0; i < n; i++) cin >> val[i];
    13   ll x = 1, num1 = 0, num2 = 0;
    14   for (int i = n - 1; i >= 0; i--) {
    15     num1 = num1 + val[i] * x;
    16     x *= base;
    17   }
    18   cin >> n >> base;
    19   for (int i = 0; i < n; i++) cin >> val[i];
    20   x = 1;
    21   for (int i = n - 1; i >= 0; i--) {
    22     num2 = num2 + val[i] * x;
    23     x *= base;
    24   }
    25   if (num1 > num2) puts(">");
    26   else if (num1 < num2) puts("<");
    27   else puts("=");
    28 }
    代码君

    题B

    题意:给你一串数字,保证相邻两个一定满足|ai – ai+1| <= 1,然后定义一个区间:这个区间的最大值和最小值的差不超过一,也就是max – min <= 1,然后问你最长的区间是多少。

    题解:dp[v][0]表示[v-1,v],dp[v][1]表示[v,v+1];然后就是来一个数,更新相应的状态,然后要注意的是因为要求的是区间,也就是连续,所以记得相应的状态变成0,也就是dp[v-1][0],dp[v+1][1],还有dp[v+2]和dp[v-2]的状态都要还原成0,就是没注意这个wa了几次。

     

     1 /*zhen hao*/
     2 #include <bits/stdc++.h>
     3 using namespace std;
     4 
     5 const int maxn = 100000 + 100;
     6 int val[maxn], dp[maxn][3];
     7 
     8 int main() {
     9   //freopen("case.in", "r", stdin);
    10   int n;
    11   scanf("%d", &n);
    12   for (int i = 1; i <= n; i++)
    13     scanf("%d", val + i);
    14   memset(dp, 0, sizeof(dp));
    15   int ans = 0;
    16   for (int i = 1; i <= n; i++) {
    17     int v = val[i];
    18     dp[v][0]++; dp[v][1]++;
    19     dp[v - 1][1]++; dp[v + 1][0]++;
    20     dp[v - 1][0] = dp[v + 1][1] = 0;
    21     if (i > 2) dp[v - 2][0] = dp[v - 2][1] = 0;
    22     dp[v + 2][0] = dp[v + 2][1] = 0;
    23     ans = max(ans, dp[v][0]);
    24     ans = max(ans, dp[v][1]);
    25     ans = max(ans, dp[v - 1][1]);
    26     ans = max(ans, dp[v + 1][0]);
    27   }
    28   cout << ans << endl;
    29 }
    代码君

    题C

    题意:给你一副图,图里面的边都是铁路,给火车行驶,然后另外没有给出的边就是巴士行驶的,问你火车和巴士能不能都从1到达n,然后max{ t1,t2}是多少。

    题解:水题,直接bfs一次即可。

     

     1 /*zhen hao*/
     2 #include <bits/stdc++.h>
     3 using namespace std;
     4 
     5 const int maxn = 500;
     6 int G[maxn][maxn], dist[maxn];
     7 int n, m;
     8 
     9 int bfs(int flag) {
    10   memset(dist, -1, sizeof dist);
    11   dist[1] = 0;
    12   queue<int> Q;
    13   Q.push(1);
    14   while (!Q.empty()) {
    15     int u = Q.front(); Q.pop();
    16     if (u == n) return dist[u];
    17     for (int i = 1; i <= n; i++) {
    18       if (G[u][i] != flag)  continue;
    19       if (dist[i] == -1) {
    20         dist[i] = dist[u] + 1;
    21         Q.push(i);
    22       }
    23     }
    24   }
    25   return -1;
    26 }
    27 
    28 int main() {
    29   //freopen("case.in", "r", stdin);
    30   scanf("%d%d", &n, &m);
    31   memset(G, 0, sizeof(G));
    32   for (int i = 0; i < m; i++) {
    33     int u, v;
    34     scanf("%d%d", &u, &v);
    35     G[u][v] = G[v][u] = 1;
    36   }
    37   int t1 = bfs(0), t2 = bfs(1);
    38   if (t1 == -1 || t2 == -1) puts("-1");
    39   else printf("%d
    ", max(t1, t2));
    40 }
    代码君

    题D

    题意:定义一种常数:

    给你一串序列,有n个整数,然后有q个询问,每个询问是一个区间[l,r],问你这个区间的所有子区间的那个常数之和是多少,输出和;

    题解:先观察这个式子可以发现,实际上j-i = 1的时候是最大的,也就是不管取什么区间都是这分母都是1,所以就是在[i,j]这个区间中的[i,i+1],[i+1,i+2]中取最大值,然后如果单纯枚举是O(n^2q),时间上行不通,最多只能跑到case10,这里用的是单调栈优化。

    现在结合我的推导详细说一下这个算的过程:

    我们知道单调栈的功能是快速算出左边比它大的,右边比它大的元素有多少个,也可以倒过来求左边和右边比自己小的有多少个,而且整个做法是O(n)。只要知道这个怎样套到这道题呢?我们知道区间里面的数每一个都有可能是一个子区间的最大值,那么这个次数是多少呢?看图:


    (7 (8) 2 1 2) 

    很显然这个8倍这5个数字共享了,答案是这个8的区间一定包含了8这个元素,有多少个呢?答案是8个,8的左边有两种选择0和1,8的右边有两种选择0123,所以2*4 = 8;也就是(左边比8小的元素 +1) × (右边比8小的元素 +1);这个就是答案。然后依次用单调栈算出即可。复杂度O(nq)

     1 /*zhen hao*/
     2 #include <bits/stdc++.h>
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 const int maxn = 1e5 + 100;
     7 ll val[maxn];
     8 
     9 struct Node {
    10   ll val;
    11   int sum;
    12 };
    13 
    14 stack<Node> S;
    15 
    16 ll f(ll x) {
    17   return x > 0 ? x : -x;
    18 }
    19 
    20 int main() {
    21  // freopen("case.in", "r", stdin);
    22   int n, q;
    23   scanf("%d%d", &n, &q);
    24   for (int i = 1; i <= n; i++)  cin >> val[i];
    25   while (q--) {
    26     int l, r;
    27     scanf("%d%d", &l, &r);
    28     ll ans = 0;
    29     for (int i = l + 1; i <= r; i++) {
    30       ll v = f(val[i] - val[i - 1]);
    31       int temp = 0;
    32       while (!S.empty() && v >= S.top().val) {
    33         ans += 1LL * S.top().sum * (temp + 1) * S.top().val;
    34         temp += S.top().sum;
    35         S.pop();
    36       }
    37       S.push((Node){v, temp + 1});
    38     }
    39     int temp = 0;
    40     while (!S.empty()) {
    41       ans += 1LL * S.top().sum * (temp + 1) * S.top().val;
    42       temp += S.top().sum;
    43       S.pop();
    44     }
    45     cout << ans << endl;
    46   }
    47   return 0;
    48 }
    代码君
  • 相关阅读:
    DFS染色解决区域分块问题UVALive 6663
    栈之逆波兰
    线段树总结
    区间合并问题
    线段树的开闭区间问题
    离散化
    线段树的学习过程
    BFS的小结
    状态数组哪家强
    卡特兰数。
  • 原文地址:https://www.cnblogs.com/zhenhao1/p/5060799.html
Copyright © 2020-2023  润新知