A. Case of the Zeros and Ones
题意: 我爱消除 - - 相邻的01就会被消除 问最后能剩下多少~
思路: 仔细观察我们发现 只要存在不相同的数 那么它们一定会被消除 最后一定为全0或者全1序列
那么答案就是abs(n_'0' - n_'1')了
参考code:
//
// Created by TaoSama on 2015-06-27
// Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n;
string s;
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
while(cin >> n >> s) {
int cnt = 0;
for(int i = 0; i < n; ++i)
if(s[i] == '0') ++cnt;
cout << abs(n - 2 * cnt) << '\n';
}
return 0;
}
B. Case of Fake Numbers
题意: 有一些gear 它们的tooth是 逆时针0-n-1放置的 奇数位置的是逆时针转 偶数位置是顺时针 问同时转多少次 可以使得序列变成0-n-1
思路: 枚举两个gear的合法状态 判断后面的gear是否合法 根据鸽笼原理 枚举n^2次就够了 (据说n次就可以了?)
参考code:
//
// Created by TaoSama on 2015-06-27
// Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n, a[1005];
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
while(cin >> n) {
for(int i = 1; i <= n; ++i) cin >> a[i];
if(n == 1) {
cout << "YES\n";
continue;
}
bool ok = false;
for(int t = 0; t <= 1e7; ++t) {
int x = (a[1] + t) % n, y = ((a[2] - t) % n + n) % n;
if(x == 0 && y == 1) {
bool can = true;
for(int i = 3; i <= n; i ++) {
if(i & 1) {
int x = (a[i] + t) % n;
if(x != i - 1) {
can = false;
break;
}
} else {
int y = ((a[i] - t) % n + n) % n;
if(y != i - 1) {
can = false;
break;
}
}
}
if(can) {
ok = true;
break;
}
}
}
cout << (ok ? "YES" : "NO") << endl;
}
return 0;
}
C. Case of Matryoshkas
题意: 俄罗斯套娃 - - 反正 仔细读题吧 最后就是求1开头的链有多长 其它的都要拆开
思路: 题读懂大家应该都会 - -
参考code:
//
// Created by TaoSama on 2015-06-27
// Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
int n, k;
vector<int> a[N];
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
while(cin >> n >> k) {
long long Max = 1, idx, ans = 0;
for(int i = 1; i <= k; ++i) {
int m; cin >> m;
a[i].clear();
for(int j = 1; j <= m; ++j) {
int x; cin >> x;
a[i].push_back(x);
}
}
for(int i = 1; i <= k; ++i) {
int cnt = 1;
if(a[i][0] == 1) {
idx = i;
for(int j = 1; j < a[i].size(); ++j) {
if(a[i][j] - a[i][j - 1] == 1) ++Max;
else break;
}
}
ans += a[i].size() - 1;
}
long long sum = n - Max + 1;
ans = ans - (a[idx].size() - 1) + (a[idx].size() - Max) + sum - 1;
cout << ans << endl;
}
return 0;
}
D. Case of Fugitive
题意: 给相邻的岛放桥 然后相邻岛的距离范围 给出了计算公式 其实就是[l2 - r1, r2 - l1]这个区间 然后看能不能放 可以输出放的姿势
思路: 贪心 两种思路都行 如果降序排序l,r 那么每次对于r找一个满足它的最大的桥 然后判断这个桥满不满足l
必须每个岛间都找到桥 找不到就是no 记录一下桥就好了
当然升序类似~ - -
参考code:
//
// Created by TaoSama on 2015-06-28
// Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 2e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
typedef long long LL;
pair<pair<LL, LL>, int> a[N];
set<pair<LL, int> > s;
int n, m, ans[N];
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
while(cin >> n >> m) {
LL _l, _r, l, r;
cin >> _l >> _r;
for(int i = 1; i < n; ++i) {
cin >> l >> r;
a[i] = {{_r - l, _l - r}, i};
_l = l, _r = r;
}
s.clear();
for(int i = 1; i <= m; ++i) {
LL x; cin >> x;
s.insert({x, i});
}
sort(a + 1, a + n);
bool ok = true;
for(int i = 1; i < n; ++i) {
LL l = -a[i].first.first, r = -a[i].first.second;
auto k = s.lower_bound({r, INF});
if(k == s.begin()) {
ok = false;
break;
}
k--;
if(k->first < l) {
ok = false;
break;
}
ans[a[i].second] = k->second;
s.erase(k);
}
if(ok) {
cout << "Yes\n";
for(int i = 1; i < n; ++i)
cout << ans[i] << ' ';
cout << '\n';
} else cout << "No\n";
}
return 0;
}
E. Case of Chocolate
题意: 每次从主对角线的一个位置出发 吃一列或者一行 如果碰到吃过的或者出边界 就不能吃了 问每次吃多少个
思路:
n = 10^9很大 - - 所以先离线然后离散化坐标~ 维护两棵线段树 X和Y X表示被吃的格子的最大的y坐标 Y同理 一开始都是0
这样 举个例子 比如 3 4 U 查询X(x = 3)得到这个max是0 然后ans = y - max = 4 - 0 = 4 然后用x = 3更新Y的[max = 0, y = 4]的区间
下次查询6 1 L 查询Y(y = 1)得到这个max是刚才的3 然后ans = x - max = 6 - 3 = 3 然后用y = 1更新X的[max = 3, x = 6]的区间
这样就ok了 可以动态建树不用离散化 改天补 然后set也可以搞
参考code:
//
// Created by TaoSama on 2015-06-28
// Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
using namespace std;
#define pr(x) cout << #x << " = " << x << " "
#define prln(x) cout << #x << " = " << x << endl
const int N = 2e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;
#define root 1, n, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
struct SegTree {
int Max[N * 6], lazy[N * 6];
void push_up(int rt) {
Max[rt] = max(Max[rt << 1], Max[rt << 1 | 1]);
}
void push_down(int rt) {
if(~lazy[rt]) {
Max[rt << 1] = max(Max[rt << 1], lazy[rt]);
Max[rt << 1 | 1] = max(Max[rt << 1 | 1], lazy[rt]);
lazy[rt << 1] = max(lazy[rt << 1], lazy[rt]);
lazy[rt << 1 | 1] = max(lazy[rt << 1 | 1], lazy[rt]);
lazy[rt] = -1;
}
}
void build(int l, int r, int rt) {
Max[rt] = 0; lazy[rt] = -1;
if(l == r) return;
int m = l + r >> 1;
build(lson);
build(rson);
push_up(rt);
}
void update(int L, int R, int v, int l, int r, int rt) {
if(L <= l && r <= R) {
lazy[rt] = max(lazy[rt], v);
Max[rt] = max(Max[rt], lazy[rt]);
return;
}
int m = l + r >> 1;
push_down(rt);
if(L <= m) update(L, R, v, lson);
if(R > m) update(L, R, v, rson);
push_up(rt);
}
int query(int o, int l, int r, int rt) {
if(l == r) return Max[rt];
int m = l + r >> 1;
push_down(rt);
if(o <= m) return query(o, lson);
else return query(o, rson);
}
};
SegTree X, Y;
int n, q;
int ox[N], oy[N];
bool vx[N], vy[N];
char op[N][2];
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);
while(scanf("%d%d", &n, &q) == 2) {
memset(vx, false, sizeof vx);
memset(vy, false, sizeof vy);
vector<int> xs, ys;
for(int i = 1; i <= q; ++i) {
scanf("%d%d%s", ox + i, oy + i, op[i]);
xs.push_back(ox[i]);
ys.push_back(oy[i]);
}
sort(xs.begin(), xs.end());
sort(ys.begin(), ys.end());
xs.resize(unique(xs.begin(), xs.end()) - xs.begin());
ys.resize(unique(ys.begin(), ys.end()) - ys.begin());
X.build(1, xs.size(), 1); Y.build(1, ys.size(), 1);
for(int i = 1; i <= q; ++i) {
int x = lower_bound(xs.begin(), xs.end(), ox[i]) - xs.begin() + 1;
int y = lower_bound(ys.begin(), ys.end(), oy[i]) - ys.begin() + 1;
// pr(x); prln(y);
if(*op[i] == 'U') {
if(vx[x]) {
puts("0");
continue;
}
vx[x] = true;
int Max = X.query(x, 1, xs.size(), 1);
// pr(Max);
printf("%d\n", oy[i] - Max);
int k = lower_bound(ys.begin(), ys.end(), Max) - ys.begin() + 1;
// pr(k); prln(ox[i]);
Y.update(k, y, ox[i], 1, ys.size(), 1);
} else {
if(vy[y]) {
puts("0");
continue;
}
vy[y] = true;
int Max = Y.query(y, 1, ys.size(), 1);
// pr(Max);
printf("%d\n", ox[i] - Max);
int k = lower_bound(xs.begin(), xs.end(), Max) - xs.begin() + 1;
// pr(k); prln(oy[i]);
X.update(k, x, oy[i], 1, xs.size(), 1);
}
}
}
return 0;
}
实在是不想写了 - - 这几天有点烦 - - 唉 - - 贴个别人写的吧~ 反正大概是这样~ 动态建树:
/*
Author: Zhouxing Shi
Created on Jun27, 2015
*/
#include <bits/stdc++.h>
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define drep(i, a, b) for (int i = (a); i >= (b); --i)
#define REP(i, a, b) for (int i = (a); i < (b); ++i)
#define pb(x) push_back(x)
#define mp(x, y) (make_pair(x, y))
#define clr(x) memset(x, 0, sizeof(x))
#define xx first
#define yy second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int inf = ~0U >> 1;
const ll INF = ~0ULL >> 1;
//***************************
map<pii, int> h;
int N, Q, x, y;
char dir[10];
struct node {
node *ls, *rs;
int m, lazy;
node() { ls = rs = NULL; m = lazy = 0; }
void cover(int d) {
m = max(m, d);
lazy = max(lazy, d);
}
void push() {
if(!ls) ls = new node();
if(!rs) rs = new node();
ls->cover(lazy);
rs->cover(lazy);
lazy = 0;
}
void upd() {
m = 0;
if(ls) m = max(m, ls->m);
if(rs) m = max(m, rs->m);
}
} ;
struct segtree {
node *rt;
void modify(node *p, int L, int R, int l, int r, int d) {
if(L == l && R == r) {
p->cover(d);
return;
}
p->push();
int m = L + R >> 1;
if(r <= m)
modify(p->ls, L, m, l, r, d);
else if(l > m)
modify(p->rs, m + 1, R, l, r, d);
else modify(p->ls, L, m, l, m, d), modify(p->rs, m + 1, R, m + 1, r, d);
p->upd();
}
int query(node *p, int L, int R, int dest) {
if(!p) return 0;
if(L == R) return p->m;
p->push();
int m = L + R >> 1;
if(dest <= m) return query(p->ls, L, m, dest);
else return query(p->rs, m + 1, R, dest);
}
} T[2];
int main() {
T[0].rt = new node();
T[1].rt = new node();
scanf("%d%d", &N, &Q);
rep(i, 1, Q) {
scanf("%d%d", &x, &y);
swap(x, y);
scanf("%s", dir);
if(h[mp(x, y)]) {
puts("0");
continue;
}
h[mp(x, y)] = 1;
if(dir[0] == 'U') {
int fst = T[0].query(T[0].rt, 1, N, y); // max
printf("%d\n", x - fst);
T[1].modify(T[1].rt, 1, N, fst + 1, x, y);
} else {
int fst = T[1].query(T[1].rt, 1, N, x); // max
printf("%d\n", y - fst);
T[0].modify(T[0].rt, 1, N, fst + 1, y, x);
}
}
return 0;
}
啊 - - 还有叉姐的set姿势 - - 模拟了一下觉得挺神奇的 - - 唉 - - 弱啊~
#include <cstdio>
#include <climits>
#include <set>
const int N = 200000 + 1;
typedef std::pair <int, int> Data;
int x[N], y[N], t[N];
int main()
{
int n, q;
scanf("%d%d", &n, &q);
x[q] = y[q] = 0;
std::set <Data> set;
set.insert({0, q});
set.insert({n + 1, q});
for (int i = 0; i < q; ++ i) {
char buffer[2];
scanf("%d%d%s", x + i, y + i, buffer);
t[i] = *buffer == 'U';
std::set <Data>::iterator iterator;
if (t[i]) {
iterator = set.lower_bound({x[i], INT_MIN});
} else {
iterator = set.upper_bound({x[i], INT_MAX});
iterator --;
}
if (x[i] == iterator->first) {
puts("0");
} else {
int j = iterator->second;
set.insert({x[i], i});
if (t[i]) {
printf("%d\n", y[i] - y[j]);
y[i] = y[j];
} else {
printf("%d\n", x[i] - x[j]);
x[i] = x[j];
}
}
}
return 0;
}