标签:out hide update pop char for span kickstart ptr
做题情况:100% + 100% + 50% + 0%, 43分, 1935名
第一题:m序列的个数(连续m个递减且最后一个为1),n<2e5
思路:用dp记录递减序列的长度
#include<bits/stdc++.h> using namespace std; const int maxn = 2e5 +10; const int INF = 0x3f3f3f3f; int n, k, a[maxn], dp[maxn]; int main() { int T, kase = 0; scanf("%d", &T); while(T--) { scanf("%d%d", &n, &k); for(int i = 0;i < n;i++) scanf("%d", &a[i]); for(int i = 0;i < n;i++) dp[i] = -INF; for(int i = n-1;i >= 0;i--) { if(a[i] == a[i+1]+1) dp[i] = dp[i+1]+1; if(a[i] == 1) dp[i] = 1; } //for(int i = 0;i < n;i++) printf("%d ", dp[i]); //printf("\n"); int ans = 0; for(int i = 0;i < n;i++) if(dp[i] == k) ans++; printf("Case #%d: %d\n", ++kase, ans); } return 0; }
第二题:给定一个字符矩阵,判断能否从底到上堆积。(字符种类数不会超过26)
思路:统计有哪些种类的字符,dfs枚举字符的排列顺序。剪枝:每次都check(path)
#include<bits/stdc++.h> using namespace std; char maze[35][35]; char poly[30]; int cnt; bool vis[30]; int r, c; int kase; bool check(vector<int>& path) { char tmaze[35][35]; for(int i = 0;i < r;i++) for(int j = 0;j < c;j++) tmaze[i][j] = maze[i][j]; int n = path.size(); for(int k = 0;k < n;k++) { for(int i = r-1;i >= 0;i--) for(int j = 0;j < c;j++) { if(tmaze[i][j] == poly[path[k]]) { if(i == r-1 || tmaze[i+1][j] == ‘a‘) { tmaze[i][j] = ‘a‘; } else return false; } } } return true; } bool dfs(int cur, vector<int>& path) // 考察到第cur个 { if(cur == cnt) { if(check(path)) { printf("Case #%d: ", ++kase); for(int i = 0;i < cnt;i++) { printf("%c", poly[path[i]]); } printf("\n"); return true; } else return false; } if(!check(path)) return false; for(int i = 0;i < cnt;i++) { if(!vis[i]) { vis[i] = true; path.push_back(i); if(dfs(cur+1, path)) return true; vis[i] = false; path.pop_back(); } } return false; } int main() { int T; scanf("%d", &T); while(T--) { //int r, c; scanf("%d%d", &r, &c); for(int i = 0;i < r;i++) scanf("%s", maze[i]); set<int>s; s.clear(); cnt = 0; for(int i = 0;i < r;i++) for(int j = 0;j < c;j++) { char c = maze[i][j]; if(s.count(c) == 0) { s.insert(c); poly[cnt++] = c; } } for(int i = 0;i < 30;i++) vis[i] = false; vector<int>path; if(!dfs(0, path)) { printf("Case #%d: -1\n", ++kase); } } return 0; }
第三题:求完美子序列(和为完全平方数的序列)的个数,N<1e5
思路:把前缀和放到map中,枚举每个位置,再枚举可能出现的平方数。
#include<bits/stdc++.h> using namespace std; using LL = long long; constexpr int maxn = -1; void work(){ int N; cin >> N; int S = 0, MS = 0; unordered_map<int, int> mp; mp[S] += 1; LL ans = 0; for(int i = 1, A; i <= N; i += 1){ cin >> A; S += A; for(int j = 0;; j += 1){ int T = S - j * j; if(T < MS) break; if(mp.count(T)) ans += mp[T]; } MS = min(MS, S); mp[S] += 1; } cout << ans << "\n"; } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); int T; cin >> T; for(int t = 1; t <= T; t += 1){ cout << "Case #" << t << ": "; work(); } return 0; }
第四题:一个序列,两种操作:查询和修改
思路:一看就是线段树,但是不会做。(这里记录一下大佬的代码,有空学习一下)
#include<bits/stdc++.h> using namespace std; using LL = long long; constexpr int maxn = 200000; #define ls (v << 1) #define rs (ls | 1) #define tm ((tl + tr) >> 1) LL A[maxn + 1]; struct Node{ LL ans, sum, size; Node operator + (const Node& node)const{ Node res; res.size = size + node.size; if(size & 1) res.sum = sum - node.sum; else res.sum = sum + node.sum; if(size & 1) res.ans = ans - node.ans - size * node.sum; else res.ans = ans + node.ans + size * node.sum; return res; } }T[maxn << 2]; void build(int v, int tl, int tr){ if(tl == tr){ T[v].size = 1; T[v].ans = T[v].sum = A[tm]; } else{ build(ls, tl, tm); build(rs, tm + 1, tr); T[v] = T[ls] + T[rs]; } } void update(int v, int tl, int tr, int x, int V){ if(tl == tr) T[v].ans = T[v].sum = V; else{ if(x <= tm) update(ls, tl, tm, x, V); else update(rs, tm + 1, tr, x, V); T[v] = T[ls] + T[rs]; } } Node query(int v, int tl, int tr, int L, int R){ if(tl >= L and tr <= R) return T[v]; if(R <= tm) return query(ls, tl, tm, L, R); if(L > tm) return query(rs, tm + 1, tr, L, R); return query(ls, tl, tm, L, R) + query(rs, tm + 1, tr, L, R); } void work(){ int N, Q; cin >> N >> Q; for(int i = 1; i <= N; i += 1) cin >> A[i]; build(1, 1, N); LL ans = 0; for(int i = 1; i <= Q; i += 1){ string s; cin >> s; if(s == "U"){ LL X, V; cin >> X >> V; update(1, 1, N, X, V); } else{ int L, R; cin >> L >> R; //cout << query(1, 1, N, L, R).ans << "\n"; ans += query(1, 1, N, L, R).ans; } } cout << ans << "\n"; } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); int T; cin >> T; for(int t = 1; t <= T; t += 1){ cout << "Case #" << t << ": "; work(); } return 0; }
标签:out hide update pop char for span kickstart ptr
原文地址:https://www.cnblogs.com/lfri/p/12907579.html