A:这题利用单调栈,先预处理出每个位置向下的最远位置,那么每一行单独考虑,每行就相当于一些段的子矩阵个数,利用单调栈维护,每次出栈的时候把大于当前要入栈(高度0的不入栈了)的段的部分计算出来,累加一下答案即可
B:这题可以枚举,因为一个10^15开3方之后是10^5枚举起来是没有问题的,然后枚举一个数字i,等于要计算在max(a, i * i * i)到min(i * i * i, b)区间,有多少个x满足i * i * x在区间内,两边除下减下就能计算出答案了
C:并查集,注意每次合并的时候都要让城市作为根,最后对于人和服务找根,如果根的范围是城市,就表明信息是是全的
D:水题,用字符串存浮点数去计算,gcd约分下即可
E:这题。。显然没有很奇葩的数据,于是只要把不能互相在一个集合的连边,然后利用二分图染色判定,如果矛盾就无解,如果不矛盾,每次就取一个子集内黑白点多的一边累加,得到的答案就是最终答案
F:树形DP,dp[u][0]和dp[u][1]分别表示不回,回树根的最小代价,那么对于一个子树,回树根的代价是固定的,就是他的子树代价+边权,那么不回的代价就是任意选一个子树不回,这样的话,只要在找子节点的过程中,记录这个答案的最大值,那么用dp[u][1]减去这个值就能得到dp[u][0]的最小值
G:大白书上有这题,先对火做一个BFS计算出每个点的蔓延时间,然后利用这个时间,在对人做一个BFS,注意这题有个坑点,就是如果人走到出口就直接出去了,因为岩浆是后蔓延到的
H:贪心,对于y操作,最好的肯定是把后面的1放到前面的0的位置,那么就是要找一个临界值,后面放X个1,其余都使用x操作一步步挪到前面,这个直接枚举,然后维护一些前缀和七七八八的东西。写起来还是要注意细节,具体见代码
代码:
A:
#include <cstdio>
#include <cstring>
#include <stack>
using namespace std;
typedef long long ll;
const int N = 2005;
int n, m;
char str[N];
int g[N][N];
stack<pair<int, int> > S;
ll get(int s, int k) {
return (ll)(2 * s - (k - 1)) * k / 2;
}
int main() {
while (~scanf("%d%d", &n, &m)) {
for (int i = 0; i < n; i++) {
scanf("%s", str);
for (int j = 0; j < m; j++) {
if (str[j] == 'b') g[i][j] = 0;
else g[i][j] = 1;
}
}
for (int i = 0; i < m; i++) {
int pre = n;
for (int j = n - 1; j >= 0; j--) {
if (g[j][i] == 0) pre = j;
g[j][i] = pre;
}
}
for (int i = 0; i < n; i++) g[i][m] = i;
ll ans = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j <= m; j++) {
int h = g[i][j] - i, v = j, pre = j;
while (!S.empty() && S.top().first > h) {
v = S.top().second;
ans += get(j - v, pre - v) * (S.top().first - h);
pre = v;
S.pop();
}
if (h) S.push(make_pair(h, v));
}
}
printf("%I64d\n", ans);
}
return 0;
}
B:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
ll a, b;
ll ans;
int main() {
while (~scanf("%I64d%I64d", &a, &b)) {
ans = 0;
for (ll i = 1; i * i * i <= b; i++) {
ll sb = max(a, i * i * i);
ans += b / (i * i) - (sb - 1) / (i * i);
}
printf("%I64d\n", ans);
}
return 0;
}
C:
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int MAXN = 400005;
const int N = 100000;
const int M = 100000;
int n, m, q;
int parent[MAXN];
int find(int x) {
if (x == parent[x])return x;
return parent[x] = find(parent[x]);
}
void uni(int a, int b) {
int pa = find(a);
int pb = find(b);
if (pb < pa) swap(pb, pa);
if (pa != pb) parent[pa] = pb;
}
int main() {
while (~scanf("%d%d%d", &n, &m, &q)) {
int a, b, c;
for (int i = 0; i < MAXN; i++)
parent[i] = i;
for (int i = 1; i <= n; i++) {
scanf("%d%d", &a, &b);
a--; b--;
if (b != -1) {
uni(a, b + N + M);
}
}
for (int i = 1; i <= m; i++) {
scanf("%d%d%d", &a, &b, &c);
a--; b--; c--;
uni(a + N, b);
if (c != -1) {
uni(a + N, c + N + M);
uni(b, c + N + M);
}
}
int tp,id;
while (q--) {
scanf("%d%d", &tp, &id);
id--;
if (tp == 1) id += N;
int x = find(id);
if (x >= N + M) printf("%d\n", x - (N + M) + 1);
else printf("0\n");
}
}
return 0;
}
D:
#include <cstdio>
#include <cstring>
int t;
char n[105];
typedef long long ll;
ll gcd(ll a, ll b) {
if (!b) return a;
return gcd(b, a % b);
}
int main() {
scanf("%d", &t);
while (t--) {
scanf("%s", &n);
int len = strlen(n);
ll sb = 0, fuck = 1;
for (int i = 0; i < len; i++) {
if (n[i] == '.') {
for (int j = i + 1; j < len; j++) {
sb = sb * 10 + n[j] - '0';
fuck *= 10;
}
break;
}
sb = sb * 10 + n[i] - '0';
}
ll d = gcd(sb, fuck);
printf("%I64d/%I64d\n", sb / d, fuck / d);
}
return 0;
}
E:
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 50005;
int n, col[N];
vector<int> g[N];
struct Point {
int x, y;
void read() {
scanf("%d%d", &x, &y);
}
} p[N];
bool cmpx(Point a, Point b) {
return a.x < b.x;
}
int w[2], ans;
bool dfs(int u) {
for (int i = 0; i < g[u].size(); i++) {
int v = g[u][i];
if (col[u] == col[v]) return false;
if (col[v] == -1) {
col[v] = !col[u];
w[col[v]]++;
dfs(v);
}
}
return true;
}
ll dis(Point a, Point b) {
ll dx = a.x - b.x;
ll dy = a.y - b.y;
return dx * dx + dy * dy;
}
int main() {
while (~scanf("%d", &n)) {
for (int i = 0; i < n; i++) {
p[i].read();
g[i].clear();
col[i] = -1;
}
sort(p, p + n, cmpx);
for (int i = 0; i < n; i++) {
for (int j = i + 1; p[j].x - p[i].x <= 5; j++) {
if (dis(p[j], p[i]) <= 25LL) {
g[i].push_back(j);
g[j].push_back(i);
}
}
}
int flag = 0;
ans = 0;
for (int i = 0; i < n; i++) {
if (col[i] == -1) {
col[i] = 0;
w[0] = 1; w[1] = 0;
if (!dfs(i)) {
flag = 1;
break;
}
ans += max(w[0], w[1]);
}
}
if (flag) printf("-1\n");
else printf("%d\n", ans);
}
return 0;
}
F:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int N = 100005;
int n;
const int INF = 0x3f3f3f3f;
int cost[N], vis[N], dp[N][2];
vector<int> g[N];
void dfs(int u) {
dp[u][0] = dp[u][1] = 0;
if (g[u].size() == 0)
return;
int Min = -INF, Minv;
for (int i = 0; i < g[u].size(); i++) {
int v = g[u][i];
dfs(v);
if (Min < dp[v][1] - dp[v][0] + cost[v]) {
Min = dp[v][1] - dp[v][0] + cost[v];
Minv = v;
}
dp[u][1] += dp[v][1] + cost[v];
}
dp[u][0] = dp[u][1] - dp[Minv][1] - cost[Minv] + dp[Minv][0];
}
int main() {
while (~scanf("%d", &n)) {
int u, v, w;
for (int i = 1; i <= n; i++) {
vis[i] = 0;
g[i].clear();
}
for (int i = 0; i < n - 1; i++) {
scanf("%d%d%d", &u, &v, &w);
g[u].push_back(v);
cost[v] = w;
}
dfs(1);
printf("%d\n", dp[1][0]);
}
return 0;
}
G:
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int N = 1005;
const int INF = 0x3f3f3f3f;
char g[N][N];
int t, n, m;
struct Point {
int x, y;
Point() {}
Point(int x, int y){
this->x = x;
this->y = y;
}
} s, e;
const int d[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
int bid[N][N], vis[N][N];
int main() {
scanf("%d", &t);
while (t--) {
scanf("%d%d", &n, &m);
queue<Point> Q;
for (int i = 0; i < n; i++) {
scanf("%s", g[i]);
for (int j = 0; j < m; j++) {
bid[i][j] = INF;
vis[i][j] = INF;
if (g[i][j] == 'S') {
s.x = i;
s.y = j;
}
if (g[i][j] == '!') {
Q.push(Point(i, j));
bid[i][j] = 0;
}
if (g[i][j] == 'E') {
e.x = i;
e.y = j;
}
}
}
while (!Q.empty()) {
Point u = Q.front(); Q.pop();
for (int i = 0; i < 4; i++) {
Point v;
v.x = u.x + d[i][0];
v.y = u.y + d[i][1];
if (v.x < 0 || v.x >= n || v.y < 0 || v.y >= m || g[v.x][v.y] == '#') continue;
if (bid[v.x][v.y] > bid[u.x][u.y] + 1) {
bid[v.x][v.y] = bid[u.x][u.y] + 1;
Q.push(v);
}
}
}
Q.push(s);
vis[s.x][s.y] = 0;
int flag = 0;
while (!Q.empty()) {
Point u = Q.front(); Q.pop();
for (int i = 0; i < 4; i++) {
Point v;
v.x = u.x + d[i][0];
v.y = u.y + d[i][1];
if (v.x < 0 || v.x >= n || v.y < 0 || v.y >= m || g[v.x][v.y] == '#') continue;
if (v.x == e.x && v.y == e.y && bid[v.x][v.y] >= vis[u.x][u.y] + 1) {
flag = 1;
break;
}
if (bid[v.x][v.y] <= vis[u.x][u.y] + 1) continue;
if (vis[v.x][v.y] > vis[u.x][u.y] + 1) {
vis[v.x][v.y] = vis[u.x][u.y] + 1;
Q.push(v);
}
}
}
printf("%s\n", flag ? "Yes" : "No");
}
return 0;
}
H:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100005;
typedef long long ll;
int t, n;
char str[N];
ll x, y;
int one[N], zero[N], on, zn;
ll sum[N], bit[N];
inline int lowbit(int x){
return x&(-x);
}
void add(int x, int v) {
while (x <= n) {
bit[x] += v;
x += lowbit(x);
}
}
ll get(int x) {
ll ans = 0;
while (x) {
ans += bit[x];
x -= lowbit(x);
}
return ans;
}
int main() {
scanf("%d", &t);
while (t--) {
scanf("%I64d%I64d", &x, &y);
scanf("%s", str + 1);
n = strlen(str + 1);
memset(bit, 0, sizeof(bit));
on = zn = 0;
ll tot = 0;
ll sb = 0;
for (int i = 1; i <= n; i++) {
sum[i] = sum[i - 1];
if (str[i] == '1') {
tot += sb;
one[on++] = i;
sum[i] += 1;
} else {
sb++;
add(i, 1);
}
}
for (int i = n; i >= 1; i--) if (str[i] == '0') zero[zn++] = i;
ll ans = 0;
while (on && zn && one[on - 1] > zero[zn - 1]) {
if (x * tot < y + x * (tot - get(one[on - 1]) - (sum[one[on - 1] - 1] - sum[zero[zn - 1]]))) {
ans += x * tot;
break;
} else {
tot -= get(one[on - 1]) + (sum[one[on - 1] - 1] - sum[zero[zn - 1]]);
add(zero[zn - 1], -1);
zn--; on--;
ans += y;
}
}
printf("%I64d\n", ans);
}
return 0;
}