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;
}