码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #333 (Div. 2)

时间:2015-12-20 14:32:20      阅读:143      评论:0      收藏:0      [点我收藏+]

标签:

因为现在太渣了只能做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\n", 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 }
代码君

 

Codeforces Round #333 (Div. 2)

标签:

原文地址:http://www.cnblogs.com/zhenhao1/p/5060799.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!