FJ三校联盟个人赛(师农工商)#1解题报告

A题—Eliminate Witches!:模拟 (hdu 4041)
这题用语法分析器来写思路就很清晰了!

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<stack>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int oo = 0x3f3f3f3f;
const ll OO = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-9;
#define lson rt<<1
#define rson rt<<1|1
void cmax(int& a, int b){ if (b>a)a = b; }
void cmin(int& a, int b){ if (b<a)a = b; }
void cmax(ll& a, ll b){ if (b>a)a = b; }
void cmin(ll& a, ll b){ if (b<a)a = b; }
void cmax(double& a, double b){ if (a - b < eps) a = b; }
void cmin(double& a, double b){ if (b - a < eps) a = b; }
void add(int& a, int b, int mod){ a = (a + b) % mod; }
void add(ll& a, ll b, ll mod){ a = (a + b) % mod; }
const int MOD = 1000000007;
const int maxn = 1100000;
char s[maxn], name[20];
stack<int>S;
vector<string>ans1;
vector<pair<int, int> >ans2;
int n, num, ii;

int get_token(){
	if (s[ii] == '(') return 1;
	if (s[ii] == ')') return 2;
	if (s[ii] == ',') return 3;
	int cnt = 0;
	while (isalpha(s[ii]))
		name[cnt++] = s[ii++];
	name[cnt] = '\0';
	return 4;
}

void solve(){
	int jud = get_token();
	if (jud == 4){
		int v = ++num;
		if (!S.empty()) ans2.push_back(make_pair(S.top(), v));
		S.push(v);
		ans1.push_back(name);
		jud = get_token();
		if (jud != 1){
			S.pop();
			if (!S.empty()) ans2.push_back(make_pair(v, S.top()));
			return;
		}
		else{
			ii++;
			while (jud != 2){
				solve();
				jud = get_token();
				ii++;
			}
			S.pop();
			if (!S.empty()) ans2.push_back(make_pair(v, S.top()));
		}
	}
}

void output(){
	printf("%d\n", ans1.size());
	for (int i = 0; i < ans1.size(); i++)
		cout << ans1[i] << endl;
	for (int i = 0; i < ans2.size(); i++)
		printf("%d %d\n", ans2[i].first, ans2[i].second);
	cout << endl;
}

void Init(){
	scanf("%s", s);
	ii = num = 0;
	ans1.clear();
	ans2.clear();
	while (!S.empty())S.pop();
	n = strlen(s);
}

int main(){
	int T;
	scanf("%d", &T);
	while (T--){
		Init();
		solve();
		output();
	}
	return 0;
}


B题—The Frog's Games: 二分  (hdu 4004)
二分最小距离,判断是否可行

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int oo = 0x3f3f3f3f;
const ll OO = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-9;
#define lson rt<<1
#define rson rt<<1|1
void cmax(int& a, int b){ if (b>a)a = b; }
void cmin(int& a, int b){ if (b<a)a = b; }
void cmax(ll& a, ll b){ if (b>a)a = b; }
void cmin(ll& a, ll b){ if (b<a)a = b; }
void cmax(double& a, double b){ if (a - b < eps) a = b; }
void cmin(double& a, double b){ if (b - a < eps) a = b; }
void add(int& a, int b, int mod){ a = (a + b) % mod; }
void add(ll& a, ll b, ll mod){ a = (a + b) % mod; }
const int MOD = 1000000007;
const int maxn = 510000;
int dis[maxn];
int L, n, m;

bool ok(int d){
	int s = 0, cnt = 0, i;
	while (s != n){
		for (i = s + 1; i <= n + 1 && dis[i] - dis[s] <= d; i++);
		if (s + 1 == i) return false;
		s = i - 1;
		cnt++;
		if (cnt > m) return false;
	}
	return true;
}

int main(){
	while (scanf("%d %d %d", &L, &n, &m) != EOF){
		for (int i = 1; i <= n; i++)scanf("%d", &dis[i]);
		dis[++n] = L;
		dis[n + 1] = oo;
		sort(dis + 1, dis + n);
		int l = 0, r = L, mid;
		while (l < r){
			mid = (l + r) >> 1;
			if (ok(mid))
				r = mid;
			else
				l = mid + 1;
		}
		printf("%d\n", r);
	}
	return 0;
}

C题—Panda:线段树  (hdu 4046)
对于要求区间中wbw的个数,可以这样设置某个点的值,表示以这个点为结尾的点是否存在wbw这样的串,那么剩下的基本就是裸线段树,单点更新,区间去和。但是有两个个需要处理的细节1、那就是这个求区间和是要这样求[a,b] query(a+2,b,1);这样是防止重复计算;2、区间更新要更新三个点,因为一个点改变会引起至多三个点的变化。之前卡在这里很久,好吧我承认我很水。

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<stack>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int oo = 0x3f3f3f3f;
const ll OO = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-9;
#define lson rt<<1
#define rson rt<<1|1
void cmax(int& a, int b){ if (b>a)a = b; }
void cmin(int& a, int b){ if (b<a)a = b; }
void cmax(ll& a, ll b){ if (b>a)a = b; }
void cmin(ll& a, ll b){ if (b<a)a = b; }
void cmax(double& a, double b){ if (a - b < eps) a = b; }
void cmin(double& a, double b){ if (b - a < eps) a = b; }
void add(int& a, int b, int mod){ a = (a + b) % mod; }
void add(ll& a, ll b, ll mod){ a = (a + b) % mod; }
const int MOD = 1000000007;
const int maxn = 51000;
char str[maxn];
struct SegTree{
	int l, r, sum;
	int mid(){ return (l + r) >> 1; }
}tree[maxn << 2];

void push_up(int rt){
	tree[rt].sum = tree[lson].sum + tree[rson].sum;
}

bool ok(int pos){
	if (pos - 2 >= 1 && str[pos - 2] == 'w'&&str[pos - 1] == 'b'&&str[pos] == 'w')
		return true;
	return false;
}

void build(int l, int r, int rt){
	tree[rt].l = l;
	tree[rt].r = r;
	tree[rt].sum = 0;
	if (l == r){
		tree[rt].sum = ok(r) ? 1 : 0;
		return;
	}
	int mid = (l + r) >> 1;
	build(l, mid, lson);
	build(mid + 1, r, rson);
	push_up(rt);
}

void update(int pos, int rt){
	if (tree[rt].l == tree[rt].r && tree[rt].r == pos){
		tree[rt].sum = ok(pos) ? 1 : 0;
		return;
	}
	int mid = tree[rt].mid();
	if (pos <= mid)
		update(pos, lson);
	else if (pos >= mid + 1)
		update(pos, rson);
	push_up(rt);
}

int query(int l, int r, int rt){
	if (l <= tree[rt].l && tree[rt].r <= r){
		return tree[rt].sum;
	}
	int res = 0;
	int mid = tree[rt].mid();
	if (l <= mid) res += query(l, r, lson);
	if (mid + 1 <= r) res += query(l, r, rson);
	return res;
}

int main(){
	//freopen("E:\\read.txt", "r", stdin);
	int n, m, T, cas = 1;
	int op, a, b;
	char c;
	scanf("%d", &T);
	while (T--){
		scanf("%d %d", &n, &m);
		scanf("%s", str + 1);
		build(1, n, 1);
		printf("Case %d:\n", cas++);
		while (m--){
			scanf("%d", &op);
			if (op == 0){
				scanf("%d %d", &a, &b);
				a++; b++;
				if (a + 2 <= b)
					printf("%d\n", query(a + 2, b, 1));
				else
					printf("0\n");
			}
			else{
				scanf("%d %c", &a, &c);
				a++;
				if (str[a] != c){
					str[a] = c;
					update(a, 1);
					if (a + 1 <= n)
						update(a + 1, 1);
					if (a + 2 <= n)
						update(a + 2, 1);
				}
			}
		}
	}
	return 0;
}

D题—Hexadecimal View:模拟题  (hdu 4054)
直接根据题意模拟,模拟题一点都不好玩!

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int oo = 0x3f3f3f3f;
const ll OO = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-9;
#define lson rt<<1
#define rson rt<<1|1
void cmax(int& a, int b){ if (b>a)a = b; }
void cmin(int& a, int b){ if (b<a)a = b; }
void cmax(ll& a, ll b){ if (b>a)a = b; }
void cmin(ll& a, ll b){ if (b<a)a = b; }
void cmax(double& a, double b){ if (a - b < eps) a = b; }
void cmin(double& a, double b){ if (b - a < eps) a = b; }
void add(int& a, int b, int mod){ a = (a + b) % mod; }
void add(ll& a, ll b, ll mod){ a = (a + b) % mod; }
const int MOD = 1000000007;
const int maxn = 550000;
char str[5000], res[50], res2[50];
char a[] = "0123456789abcdef";

void gao(int n){
	res[0] = a[n / 16];
	res[1] = a[n % 16];
	res[3] = '\0';
}

void gao2(int n){
	res2[0] = a[n / 16 / 16 / 16 % 16];
	res2[1] = a[n / 16 / 16 % 16];
	res2[2] = a[n / 16 % 16];
	res2[3] = a[n % 16];
	res2[4] = '\0';
}

void put_char(char c){
	if (isupper(c))
		printf("%c", tolower(c));
	else
		printf("%c", toupper(c));
}

int main(){
	//freopen("E:\\read.txt", "r", stdin);
	while (gets(str)){
		int n = strlen(str);
		int i = 0, cnt;
		for (i = 0; str[i]; i++){
			if (i % 16 == 0){
				gao2(i);
				printf("%s:", res2);
				cnt = 41;
			}
			if (i % 2 == 0) printf(" ");
			gao(str[i]);
			printf("%s", res);
			if (i % 2 == 0)cnt -= 3;
			else cnt -= 2;
			if (i % 16 == 15 || i == n - 1){
				for (int j = 1; j <= cnt; j++)printf(" ");
				for (int j = i - i % 16; j <= i; j++)
					put_char(str[j]);
				puts("");
			}
		}
	}
	return 0;
}



E题—Number String:动态规划  (hdu 4055)
dp,这题状态很简单f[i][j]前i个数第i个数选择j对应排列数。
对于I比价好转移f[i][j] = f[i-1][1]+.....+f[i-1][j-1]
对于D因为排列有的性质,同时加上一个数不引排列的组合数改变那么:
f[i][j] = f[i-1][j]+....+f[i-1][i-1]
这样计算就变成了O(n^3)果然要跪,但是可以用前缀和优化。
g[i][j]表示前i个数小于等于j的数对应组合方案
我的代码将i错位了一下(相当于i表示数列的第i+1个数)。

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int oo = 0x3f3f3f3f;
const ll OO = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-9;
#define lson rt<<1
#define rson rt<<1|1
void cmax(int& a, int b){ if (b>a)a = b; }
void cmin(int& a, int b){ if (b<a)a = b; }
void cmax(ll& a, ll b){ if (b>a)a = b; }
void cmin(ll& a, ll b){ if (b<a)a = b; }
void cmax(double& a, double b){ if (a - b < eps) a = b; }
void cmin(double& a, double b){ if (b - a < eps) a = b; }
void add(int& a, int b, int mod){ a = (a + b) % mod; }
void add(ll& a, ll b, ll mod){ a = (a + b) % mod; }
const int MOD = 1000000007;
const int maxn = 1100;
int f[maxn][maxn], g[maxn][maxn];
char str[maxn];

int main(){
	//freopen("E:\\read.txt", "r", stdin);
	while (scanf("%s", str + 1) != EOF){
		int n = strlen(str + 1);
		for (int i = 1; i <= n; i++)g[0][1] = 1;
		for (int i = 1; i <= n; i++){
			for (int j = 1; j <= i + 1; j++){
				f[i][j] = g[i][j] = 0;
				if (str[i] == 'I' || str[i] == '?')
					f[i][j] = (f[i][j] + g[i - 1][j - 1]) % MOD;
				if (str[i] == 'D' || str[i] == '?')
					f[i][j] = (f[i][j] + g[i - 1][i] - g[i - 1][j - 1] + MOD) % MOD;
				g[i][j] = (g[i][j - 1] + f[i][j]) % MOD;
			}
		}
		cout << g[n][n + 1] << endl;
	}
	return 0;
}

F题—The kth great number: 优先队列  (hdu 4006)
这题优先队列存前k大的数,每次判断是否比第k大的数大(就是队列顶部的数),如果大出队替换!

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int oo = 0x3f3f3f3f;
const ll OO = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-9;
#define lson rt<<1
#define rson rt<<1|1
void cmax(int& a, int b){ if (b>a)a = b; }
void cmin(int& a, int b){ if (b<a)a = b; }
void cmax(ll& a, ll b){ if (b>a)a = b; }
void cmin(ll& a, ll b){ if (b<a)a = b; }
void cmax(double& a, double b){ if (a - b < eps) a = b; }
void cmin(double& a, double b){ if (b - a < eps) a = b; }
void add(int& a, int b, int mod){ a = (a + b) % mod; }
void add(ll& a, ll b, ll mod){ a = (a + b) % mod; }
const int maxn = 10000;
struct Node{
	int val;
	bool operator<(const Node &a)const{
		return a.val < val;
	}
	Node(){}
	Node(int a){
		val = a;
	}
};
priority_queue<Node>q;

int main(){
	int n, k, num;
	char op;
	while (scanf("%d%d", &n, &k) != EOF){
		while (!q.empty())q.pop();
		while (n--){
			getchar();
			scanf("%c", &op);
			if (op == 'I'){
				scanf("%d", &num);
				if (q.size() < k || q.empty())
					q.push(Node(num));
				else if (num>q.top().val){
					q.pop();
					q.push(Node(num));
				}
			}else{
				printf("%d\n", q.top());
			}
		}
	}
	return 0;
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值