Codeforces Round #353(Div 2)
2016-05-27 22:05
239 查看
信息课闲着无聊打的一场cf模拟赛。
已知一个等差数列的首项和公差,问某个数在不在等差数列内?
*题解:
直接模拟,注意零和负数要判,不然直接模会出错。
*代码:
已知一个3*3矩阵的(1,2)(2,1)(2,3)(3,2)四个点,求剩下的五个空有多少种不同的方案,使得每个2*2方格内的数之和都相等,同时保证填上去的数都在1~n范围内。
*题解:
设左上角的数为x,根据等量关系可以推出剩下三个角上面的表达式,然后就枚举x,判断剩下三个数是不是合法的就可以,中间那个数填什么都可以,所以答案*n就可以了。
*代码:
有一个长度为n的数组a,每一次可以将某个位置的数移到旁边的位置上(1的旁边是2和n,n的旁边是n-1和1),问最少的移动步数是多少?
*题解:
答案就是n-前缀和出现次数的最多的次数。因为这是一个环,每次出现一个和为0的段,那么此处的答案就是这段的长度-1,所以只要统计有多少个答案为0的段。所以我们把所有的前缀和都取出来,两个相同的前缀和之间一定是和为0的段,所以n-出现次数最多的前缀和就是答案。
*代码:
给定一棵BST的插入的顺序,输出每次插入的节点的父亲。
*题解:
比赛的时候sb地写了一个模拟每次在BST上暴力插,结果交上去光荣地T了,突然想到一条链的话就被卡成n2的了。然后自己画了画图,发现答案就是序列里的upper_bound。我当时对此的解决方法是离散化后用链表把所有的数串起来,然后倒序处理插入操作,这样就变成了在树上的删除操作,可以用链表来维护,这样它的父亲就是链表左右两端的出现时间的较大值。(我也不知道当时是怎么想出这个算法的,也不知道是不是对的,但是不知道为什么交上去运气好居然就ac了)
*代码:
有n个站点,对于站点i(1≤i<n) ,它到达i+1 到 ai的代价都为1,且不能往编号小于它的点走。求最短路的邻接矩阵的总和。
*题解:
第一眼是floyd,发现数据范围跑不过。(于是考场就弃疗了),于是就想DP,对于每个i,枚举自己所能到达的点的ai 最大的点。写出DP方程:dpi=dpj−(ai−j)+n−i−1,其中j为上述的最优的点。然后j可以用线段树/树状数组/ST表来维护,于是复杂度降为O(nlogn)。
*代码:
A题:
*题目描述:已知一个等差数列的首项和公差,问某个数在不在等差数列内?
*题解:
直接模拟,注意零和负数要判,不然直接模会出错。
*代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #ifdef WIN32 #define LL "%I64d" #else #define LL "%lld" #endif #ifdef CT #define debug(...) printf(__VA_ARGS__) #define setfile() #else #define debug(...) #define filename "" #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout); #endif #define R register #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++) #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b)) #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b)) #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0) #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0) char B[1 << 15], *S = B, *T = B; inline int FastIn() { R char ch; R int cnt = 0; R bool minus = 0; while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ; ch == '-' ? minus = 1 : cnt = ch - '0'; while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0'; return minus ? -cnt : cnt; } int main() { // setfile(); R int a = FastIn(), b = FastIn(), c = FastIn(); bool ans; if (!c) ans = a == b; else if (c > 0) ans = b >= a && ((b - a) % c == 0); else ans = b <= a && ((a - b) % (-c) == 0); printf(ans ? "YES" : "NO"); return 0; }
B题:
*题目描述:已知一个3*3矩阵的(1,2)(2,1)(2,3)(3,2)四个点,求剩下的五个空有多少种不同的方案,使得每个2*2方格内的数之和都相等,同时保证填上去的数都在1~n范围内。
*题解:
设左上角的数为x,根据等量关系可以推出剩下三个角上面的表达式,然后就枚举x,判断剩下三个数是不是合法的就可以,中间那个数填什么都可以,所以答案*n就可以了。
*代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #ifdef WIN32 #define LL "%I64d" #else #define LL "%lld" #endif #ifdef CT #define debug(...) printf(__VA_ARGS__) #define setfile() #else #define debug(...) #define filename "" #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout); #endif #define R register #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++) #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b)) #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b)) #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0) #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0) char B[1 << 15], *S = B, *T = B; inline int FastIn() { R char ch; R int cnt = 0; R bool minus = 0; while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ; ch == '-' ? minus = 1 : cnt = ch - '0'; while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0'; return minus ? -cnt : cnt; } int main() { // setfile(); R int n = FastIn(), a = FastIn(), b = FastIn(), c = FastIn(), d = FastIn(); R long long ans = 0; #define ok(_x) ((_x) >= 1 && (_x) <= n) for (R int i = 1; i <= n; ++i) if (ok(i + b - c) && ok(i + a - d) && ok(i + a + b - c - d)) ++ans; printf(LL"\n", ans * n); return 0; }
C题:
*题目描述:有一个长度为n的数组a,每一次可以将某个位置的数移到旁边的位置上(1的旁边是2和n,n的旁边是n-1和1),问最少的移动步数是多少?
*题解:
答案就是n-前缀和出现次数的最多的次数。因为这是一个环,每次出现一个和为0的段,那么此处的答案就是这段的长度-1,所以只要统计有多少个答案为0的段。所以我们把所有的前缀和都取出来,两个相同的前缀和之间一定是和为0的段,所以n-出现次数最多的前缀和就是答案。
*代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #ifdef WIN32 #define LL "%I64d" #else #define LL "%lld" #endif #ifdef CT #define debug(...) printf(__VA_ARGS__) #define setfile() #else #define debug(...) #define filename "" #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout); #endif #define R register #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++) #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b)) #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b)) #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0) #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0) char B[1 << 15], *S = B, *T = B; inline int FastIn() { R char ch; R int cnt = 0; R bool minus = 0; while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ; ch == '-' ? minus = 1 : cnt = ch - '0'; while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0'; return minus ? -cnt : cnt; } #include <map> std::map<long long, int> cnt; int main() { // setfile(); R int n = FastIn(), ans = 1; R long long s = 0; for (R int i = 1; i <= n; ++i) { s += FastIn(); ++cnt[s]; cmax(ans, cnt[s]); } printf("%d\n", n - ans ); return 0; }
D题:
*题目描述:给定一棵BST的插入的顺序,输出每次插入的节点的父亲。
*题解:
比赛的时候sb地写了一个模拟每次在BST上暴力插,结果交上去光荣地T了,突然想到一条链的话就被卡成n2的了。然后自己画了画图,发现答案就是序列里的upper_bound。我当时对此的解决方法是离散化后用链表把所有的数串起来,然后倒序处理插入操作,这样就变成了在树上的删除操作,可以用链表来维护,这样它的父亲就是链表左右两端的出现时间的较大值。(我也不知道当时是怎么想出这个算法的,也不知道是不是对的,但是不知道为什么交上去运气好居然就ac了)
*代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #ifdef WIN32 #define LL "%I64d" #else #define LL "%lld" #endif #ifdef CT #define debug(...) printf(__VA_ARGS__) #define setfile() #else #define debug(...) #define filename "" #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout); #endif #define R register #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++) #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b)) #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b)) #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0) #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0) char B[1 << 15], *S = B, *T = B; inline int FastIn() { R char ch; R int cnt = 0; R bool minus = 0; while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ; ch == '-' ? minus = 1 : cnt = ch - '0'; while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0'; return minus ? -cnt : cnt; } #define maxn 100010 int a[maxn], b[maxn], next[maxn], prev[maxn], n, tim[maxn], ans[maxn]; int main() { // setfile(); n = FastIn(); for (R int i = 1; i <= n; ++i) a[i] = b[i] = FastIn(); std::sort(b + 1, b + n + 1); for (R int i = 1; i <= n; ++i) a[i] = std::lower_bound(b + 1, b + n + 1, a[i]) - b, tim[a[i]] = i, next[i] = i + 1, prev[i] = i - 1; tim[0] = tim[n + 1] = 0; for (R int i = n; i > 1; --i) { next[prev[a[i]]] = next[a[i]]; prev[next[a[i]]] = prev[a[i]]; ans[i] = b[tim[next[a[i]]] > tim[prev[a[i]]] ? next[a[i]] : prev[a[i]]]; } for (R int i = 2; i <= n; ++i) printf("%d ", ans[i] ); return 0; }
E题:
*题目描述:有n个站点,对于站点i(1≤i<n) ,它到达i+1 到 ai的代价都为1,且不能往编号小于它的点走。求最短路的邻接矩阵的总和。
*题解:
第一眼是floyd,发现数据范围跑不过。(于是考场就弃疗了),于是就想DP,对于每个i,枚举自己所能到达的点的ai 最大的点。写出DP方程:dpi=dpj−(ai−j)+n−i−1,其中j为上述的最优的点。然后j可以用线段树/树状数组/ST表来维护,于是复杂度降为O(nlogn)。
*代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #ifdef WIN32 #define LL "%I64d" #else #define LL "%lld" #endif #ifdef CT #define debug(...) printf(__VA_ARGS__) #define setfile() #else #define debug(...) #define filename "" #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout); #endif #define R register #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++) #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b)) #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b)) #define cmax(_a, _b) (_a < (_b) ? _a = (_b), 0 : 0) #define cmin(_a, _b) (_a > (_b) ? _a = (_b), 0 : 0) char B[1 << 15], *S = B, *T = B; inline int FastIn() { R char ch; R int cnt = 0; R bool minus = 0; while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ; ch == '-' ? minus = 1 : cnt = ch - '0'; while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0'; return minus ? -cnt : cnt; } #define maxn 1 << 20 int a[maxn], M, n; struct Seg { int val, pos; inline bool operator < (const Seg &that) const {return val < that.val || (val == that.val && pos < that.pos); } inline bool operator > (const Seg &that) const {return val > that.val || (val == that.val && pos > that.pos); } }tr[maxn]; inline void Build() { for (R int i = 0; i < n; ++i) tr[i + M] = (Seg){a[i], i}; for (R int i = M - 1; i; --i) tr[i] = dmax(tr[i << 1], tr[i << 1 | 1]); } inline int get(R int s, R int t) { Seg ans = (Seg) {-1, -1}; for (s = s + M - 1, t = t + M + 1; s ^ t ^ 1; s >>= 1, t >>= 1) { if (~ s & 1) cmax(ans, tr[s ^ 1]); if (t & 1) cmax(ans, tr[t ^ 1]); } return ans.pos; } long long dp[maxn]; int main() { // setfile(); n = FastIn(); for (R int i = 0; i < n - 1; ++i) a[i] = FastIn() - 1; a[n - 1] = n - 1; for (M = 1; M < n; M <<= 1); Build(); R long long ans = 0; for (R int i = n - 2; i >= 0; --i) { R int m = get(i + 1, a[i]); dp[i] = dp[m] - (a[i] - m) + n - i - 1; ans += dp[i]; } printf(LL"\n", ans); return 0; }
相关文章推荐
- Codeforces Round #197 (Div. 2)
- Codeforces Round #198 (Div. 1)
- Codeforces 405E Codeforces Round #238 (Div. 2)E
- Codeforces 407C Codeforces Round #239 (Div. 1)C
- CodeForces 449A - Jzzhu and Chocolate
- CodeForces 449 B. Jzzhu and Cities
- codeforces 618C. Constellation
- Codeforces Round #349 (Div. 2) - C
- Codeforces Round #265 (Div. 2)
- Codeforces #310 div2 C. Case of Matryoshkas
- 状态压缩DP codeforces 244 Problem C. The Brand New Function 和 codeforces 165 E. Compatible Numbers
- codeforces 16 Problem E fish
- Codeforces Round332 部分题解
- CodeForces 603A_Alternative Thinking (DP)
- CodeForces 602B_Approximating a Constant Range_DP
- Codeforces round #247 for Div. 2
- Codeforces Round #246 (Div. 2)
- Codeforces #264(div 2)D.Gargari and Permutations
- Codeforces Round #236 (Div. 2)------A,B
- codeforces 257 div2 B