【训练赛地址】点击打开链接
【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;
}