【玩耍】一水

    xiaoxiao2021-12-14  21

    【训练赛地址】点击打开链接

    【PS】由于几乎是中文题目和题目比较短,就不说题意了。

    【A】中文题目,状压+BFS,没有什么坑点,上代码。

    【AC代码】

    // //Created by just_sort 2016/12/1 //Copyright (c) 2016 just_sort.All Rights Reserved // #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> #include <ext/pb_ds/hash_policy.hpp> #include <set> #include <map> #include <queue> #include <stack> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; using namespace __gnu_pbds; typedef long long LL; typedef pair<int, LL> pp; #define MP(x,y) make_pair(x,y) const int maxn = 200005; typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>order_set; //head int n, m, tt, sx, sy; int dir[4][2] = {{0,1},{0,-1},{-1,0},{1,0}}; char maze[22][22]; bool vis[22][22][1<<10]; struct node{ int x, y, t, state; node(){} node(int x, int y, int t, int state):x(x), y(y), t(t), state(state){} }; int getid(char c) { if(islower(c)){ return c - 'a'; } else{ return c - 'A'; } } int bfs() { queue<node>q; node now, nex; now = node(sx, sy, 0, 0); q.push(now); vis[sx][sy][0] = 1; while(!q.empty()){ now = q.front(); q.pop(); if(now.t >= tt) break; for(int i = 0; i < 4; i++){ int dx = now.x + dir[i][0]; int dy = now.y + dir[i][1]; int t = now.t + 1; int state = now.state; if(vis[dx][dy][state] || dx < 0 || dx >= n || dy < 0 || dy >= m || maze[dx][dy] == '*'){ continue; } if(isupper(maze[dx][dy]) && !(state & (1<<getid(maze[dx][dy])))) continue; if(islower(maze[dx][dy])) state |= (1<<getid(maze[dx][dy])); if(maze[dx][dy] == '^') return t; if(!vis[dx][dy][state]){ vis[dx][dy][state] = 1; q.push(node(dx, dy, t, state)); } } } return -1; } int main() { while(scanf("%d%d%d",&n,&m,&tt)!=EOF) { tt -= 1; memset(vis, false, sizeof(vis)); for(int i = 0; i < n; i++) scanf("%s", maze[i]); for(int i = 0; i < n; i++){ for(int j = 0; j < m; j++){ if(maze[i][j] == '@'){ sx = i, sy = j, maze[i][j] = '.'; break; } } } int ans = bfs(); printf("%d\n",ans); } return 0; } 【B】先考虑每一行,再考虑一下每一行里面的元素,发现解决的这个问题有大量的重叠子问题,一个简单的dp想法就由然而生了。

    【代码君】

    // //Created by just_sort 2016/12/1 //Copyright (c) 2016 just_sort.All Rights Reserved // #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> #include <ext/pb_ds/hash_policy.hpp> #include <set> #include <map> #include <queue> #include <stack> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; using namespace __gnu_pbds; typedef long long LL; typedef pair<int, LL> pp; #define MP(x,y) make_pair(x,y) const int maxn = 200005; typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>order_set; //head int dp1[maxn], dp2[maxn]; int n, m; int main() { while(scanf("%d%d",&n,&m)!=EOF) { memset(dp1, 0, sizeof(dp1)); memset(dp2, 0, sizeof(dp2)); for(int i = 2; i <= n + 1; i++){ for(int j = 2; j <= m + 1; j++){ int x; scanf("%d", &x); dp1[j] = max(dp1[j-1], dp1[j-2]+x); } dp2[i] = max(dp2[i-1], dp2[i-2] + dp1[m + 1]); } printf("%d\n", dp2[n+1]); } return 0; } 【C】就是线段树的区间合并问题,不过这个题要维护的东西有点多,看代码吧。

    // //Created by just_sort 2016/12/1 //Copyright (c) 2016 just_sort.All Rights Reserved // //#include <ext/pb_ds/assoc_container.hpp> //#include <ext/pb_ds/tree_policy.hpp> //#include <ext/pb_ds/hash_policy.hpp> //#include <set> //#include <map> //#include <queue> //#include <stack> //#include <cmath> //#include <cstdio> //#include <cstdlib> //#include <cstring> //#include <iostream> //#include <algorithm> //using namespace std; //using namespace __gnu_pbds; //typedef long long LL; //typedef pair<int, LL> pp; //#define MP(x,y) make_pair(x,y) const int maxn = 200005; //typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>order_set; //head #include <cstdio> #include <iostream> #include <algorithm> using namespace std; struct node{ int l, r, len; int l0, l1;//左端点开始的0,1的个数 int r0, r1;//右端点开始的0,1的个数 int max0, max1, cnt0, cnt1, flag;//区间连续0,1的个数,区间0,1的个数 }Tree[maxn<<2]; int n, m, A[maxn]; void pushup(int rt) { Tree[rt].l0 = Tree[rt*2].l0; if(Tree[rt*2].l0 == Tree[rt*2].len) Tree[rt].l0 += Tree[rt*2+1].l0; Tree[rt].r0 = Tree[rt*2+1].r0; if(Tree[rt*2+1].r0 == Tree[rt*2+1].len) Tree[rt].r0 += Tree[rt*2].r0; Tree[rt].max0 = max(Tree[rt*2].max0, Tree[rt*2+1].max0); Tree[rt].max0 = max(Tree[rt].max0, Tree[rt*2].r0 + Tree[rt*2+1].l0); Tree[rt].cnt0 = Tree[rt*2].cnt0 + Tree[rt*2+1].cnt0; Tree[rt].l1 = Tree[rt*2].l1; if(Tree[rt*2].l1 == Tree[rt*2].len) Tree[rt].l1 += Tree[rt*2+1].l1; Tree[rt].r1 = Tree[rt*2+1].r1; if(Tree[rt*2+1].r1 == Tree[rt*2+1].len) Tree[rt].r1 += Tree[rt*2].r1; Tree[rt].max1 = max(Tree[rt*2].max1, Tree[rt*2+1].max1); Tree[rt].max1 = max(Tree[rt].max1, Tree[rt*2].r1 + Tree[rt*2+1].l1); Tree[rt].cnt1 = Tree[rt*2].cnt1 + Tree[rt*2+1].cnt1; //Tree[rt].len = Tree[rt*2].len + Tree[rt*2+1].len; } void Build(int l, int r, int rt) { Tree[rt].l = l, Tree[rt].r = r, Tree[rt].len = r - l + 1, Tree[rt].flag = -1; if(l == r){ Tree[rt].l0 = Tree[rt].r0 = Tree[rt].max0 = Tree[rt].cnt0 = !A[l]; Tree[rt].l1 = Tree[rt].r1 = Tree[rt].max1 = Tree[rt].cnt1 = A[l]; return ; } int mid = (l + r) / 2; Build(l, mid, rt*2); Build(mid+1, r, rt*2+1); pushup(rt); } void update(int L, int R, int rt, int cmd) { if(Tree[rt].l == L && Tree[rt].r == R){ if(cmd == 0) { Tree[rt].l0 = Tree[rt].r0 = Tree[rt].max0 = Tree[rt].cnt0 = Tree[rt].len; Tree[rt].l1 = Tree[rt].r1 = Tree[rt].max1 = Tree[rt].cnt1 = 0; Tree[rt].flag = 0; } else if(cmd == 1){ Tree[rt].l0 = Tree[rt].r0 = Tree[rt].max0 = Tree[rt].cnt0 = 0; Tree[rt].l1 = Tree[rt].r1 = Tree[rt].max1 = Tree[rt].cnt1 = Tree[rt].len; Tree[rt].flag = 1; } else if(cmd == 2){ swap(Tree[rt].l0, Tree[rt].l1); swap(Tree[rt].r0, Tree[rt].r1); swap(Tree[rt].max0, Tree[rt].max1); swap(Tree[rt].cnt0, Tree[rt].cnt1); Tree[rt].flag = 1 - Tree[rt].flag; } return ; } //lazy 操作 if(Tree[rt].flag >= 0){ update(Tree[rt*2].l, Tree[rt*2].r, rt*2, Tree[rt].flag); update(Tree[rt*2+1].l, Tree[rt*2+1].r, rt*2+1, Tree[rt].flag); Tree[rt].flag = -1; } int mid = (Tree[rt].l + Tree[rt].r) / 2; if(R <= mid) update(L, R, rt*2, cmd); else if(L > mid) update(L, R, rt*2+1, cmd); else { update(L, mid, rt*2, cmd); update(mid+1, R, rt*2+1, cmd); } pushup(rt); } node query(int L, int R, int rt) { if(L == Tree[rt].l && Tree[rt].r == R) return Tree[rt]; //lazy 操作 if(Tree[rt].flag >= 0){ update(Tree[rt*2].l, Tree[rt*2].r, rt*2, Tree[rt].flag); update(Tree[rt*2+1].l, Tree[rt*2+1].r, rt*2+1, Tree[rt].flag); Tree[rt].flag = -1; } int mid = (Tree[rt].l + Tree[rt].r) / 2; if(R <= mid) return query(L, R, rt*2); else if(L > mid) return query(L, R, rt*2+1); else{ node t1, t2, t3; t1 = query(L, mid, rt*2); t2 = query(mid+1, R, rt*2+1); t3.cnt1 = t1.cnt1 + t2.cnt1; t3.l1 = t1.l1; if(t1.l1 == t1.len) t3.l1 += t2.l1; t3.r1 = t2.r1; if(t2.r1 == t2.len) t3.r1 += t1.r1; t3.max1 = max(t1.max1, t2.max1); t3.max1 = max(t3.max1, t1.r1 + t2.l1); t3.len = t1.len + t2.len; return t3; } } int main() { int n, m; while(scanf("%d%d",&n,&m) != EOF) { for(int i = 1; i <= n; i++) scanf("%d", &A[i]); Build(1, n, 1); int op, a, b; for(int i = 1; i <= m; i++){ scanf("%d%d%d",&op,&a,&b); a++; b++; if(op <= 2){ update(a, b, 1, op); } else{ node ans = query(a, b, 1); if(op == 3){ printf("%d\n",ans.cnt1); } else{ printf("%d\n",ans.max1); } } } } return 0; } 【D】贪心+排序, 按比率排,避免小数,所以讲式子进行转换

    【代码君】

    // //Created by just_sort 2016/12/1 //Copyright (c) 2016 just_sort.All Rights Reserved // #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> #include <ext/pb_ds/hash_policy.hpp> #include <set> #include <map> #include <queue> #include <stack> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; using namespace __gnu_pbds; typedef long long LL; typedef pair<int, LL> pp; #define MP(x,y) make_pair(x,y) const int maxn = 200005; typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>order_set; //head struct node{ int dps, hp; node(){} node(int dps, int hp):dps(dps), hp(hp){} bool operator <(const node &rhs) const{ return (hp*rhs.dps) < (dps*rhs.hp); } void read(){ scanf("%d%d",&dps,&hp); } }a[22]; int main() { int n; while(scanf("%d",&n)!=EOF) { for(int i = 0; i < n; i++) a[i].read(); sort(a, a + n); int sum = 0; int ans = 0; for(int i = 0; i < n; i++){ sum = sum + a[i].dps; } for(int i = 0; i < n; i++){ ans = ans + sum * a[i].hp; sum = sum - a[i].dps; } printf("%d\n", ans); } return 0; } 【E】 将不小于m的数看成1,剩下的看成0,只要区间1的个数不小于k就可以,枚举区间左端点,右端点可以通过two-pointers求出,时间复杂度O(n)

    【代码君】

    // //Created by just_sort 2016/12/1 //Copyright (c) 2016 just_sort.All Rights Reserved // #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> #include <ext/pb_ds/hash_policy.hpp> #include <set> #include <map> #include <queue> #include <stack> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; using namespace __gnu_pbds; typedef long long LL; typedef pair<int, LL> pp; #define MP(x,y) make_pair(x,y) const int maxn = 200005; typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>order_set; //head int a[maxn]; int n, m, K; LL ans; int main() { int T, n; scanf("%d",&T); while(T--){ scanf("%d%d%d", &n,&m,&K); for(int i = 1; i <= n; i++) scanf("%d",&a[i]); ans = 0; int r = 0, num = 0; for(int i = 1; i <= n; i++){ while(num < K && r <= n){r++; num += (a[r] >= m);} if(num < K) break; ans += n - r + 1; num -= (a[i] >= m); } printf("%lld\n",ans); } return 0; }

    转载请注明原文地址: https://ju.6miu.com/read-964017.html

    最新回复(0)