杂题练习10.15

版权声明:博主是菜鸡,但转的时候还是说一声吧 https://blog.csdn.net/qq_37666409/article/details/83187722

Atcoder3958

手画几步就发现规律了,操作奇数次就是b-a,偶数就是a-b

#include <bits/stdc++.h>
#define LL long long
#define db double
using namespace std;

template <typename T> inline void read(T &x) {
	char c = getchar();
	bool f = false;
	for (x = 0; !isdigit(c); c = getchar()) {
		if (c == '-') {
			f = true;
		}
	}
	for (; isdigit(c); c = getchar()) {
		x = x * 10 + c - '0';
	}
	if (f) {
		x = -x;
	}
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
	return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
	return a > b ? a = b, true : false;
}

int main() {
	int a, b, c;
	LL k;
	read(a), read(b), read(c), read(k);
	if (k & 1) {
		printf("%d\n", b - a);
	} else {
		printf("%d\n", a - b);
	}
	return 0;
}

Atcoder3959

考虑将问题变成将两边的数插入到中间来排序

明显n-最长上升子序列就是答案

#include <bits/stdc++.h>
#define LL long long
#define db double
using namespace std;

const int MAXN = 200200;
const int INF = 0x3f3f3f3f;

template <typename T> inline void read(T &x) {
	char c = getchar();
	bool f = false;
	for (x = 0; !isdigit(c); c = getchar()) {
		if (c == '-') {
			f = true;
		}
	}
	for (; isdigit(c); c = getchar()) {
		x = x * 10 + c - '0';
	}
	if (f) {
		x = -x;
	}
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
	return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
	return a > b ? a = b, true : false;
}

int n, a[MAXN];
int cnt;
#define ls lower_bound
#define us upper_bound

signed main() {
	read(n);
	for(int i = 1, x; i <= n; i++) read(x), a[x] = i;
	int ans = 0;
	for(int i = 1, len = 0; i <= n; i++) {
		if(a[i] > a[i - 1]) {
			CheckMax(ans, ++len);
		}
		else len = 1;
	}
	printf("%d\n", n - ans);
	return 0;
}

Gym101773D

有点毒

一看求最大最小,二分答案!

然后就想这个Check怎么写

明显如果一个节点x的子节点v能接受的最大范围是[L, R]

那么x能接受的最大范围就是[L - ans, R - ans]

在所有儿子中L - ans取max, R - ans取min,如果最后R < L就不行

*的节点特判一下

#include <bits/stdc++.h>
#define LL long long
#define db double
using namespace std;

const int MAXN = 100100;
const int MAXE = 200200;
const int INF = 0x3f3f3f3f;
const double eps = 1e-7;

template <typename T> inline void read(T &x) {
	char c = getchar();
	bool f = false;
	for (x = 0; !isdigit(c); c = getchar()) {
		if (c == '-') {
			f = true;
		}
	}
	for (; isdigit(c); c = getchar()) {
		x = x * 10 + c - '0';
	}
	if (f) {
		x = -x;
	}
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
	return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
	return a > b ? a = b, true : false;
}

struct Edge {
	int to, nxt;
	Edge() {}
	Edge(int _to, int _nxt) : to(_to), nxt(_nxt) {}
}E[MAXE];

int h[MAXN], fa[MAXN], dep[MAXN], cnt;

inline void add_edge(int u, int v) {
	E[++cnt] = Edge(v, h[u]), h[u] = cnt;
	E[++cnt] = Edge(u, h[v]), h[v] = cnt;
}

bool isv[MAXN];
double L[MAXN], R[MAXN];
int v[MAXN], n;
bool cpy[MAXN];
double mid;

bool dfs(int x) {
	if(isv[x]) cpy[x] = 1;
	else cpy[x] = 0, L[x] = R[x] = v[x];
	for(int i = h[x]; i; i = E[i].nxt) {
		int to = E[i].to;
		if(to == fa[x]) continue;
		fa[to] = x;
		if(!dfs(to)) return 0;
		if(!cpy[to]) {
			if(cpy[x]) {
				cpy[x] = 0, L[x] = L[to] - mid, R[x] = R[to] + mid;
			}
			else {
				CheckMax(L[x], L[to] - mid);
				CheckMin(R[x], R[to] + mid);
			}
		}
	}
	return cpy[x] || (L[x] < R[x] + eps);
}

signed main() {
	read(n);
	for(int i = 1; i <= n; i++) {
		char s[20];
		scanf("%s", s);
		if(s[0] == '*') isv[i] = 1;
		else sscanf(s, "%d", &v[i]);
	}
	for(int i = 1; i < n; i++) {
		int x, y;
		read(x), read(y);
		add_edge(x, y);
	}
	double l = 0, r = 2000000;
	while(r - l > eps) {
		mid = (l + r) / 2;
		if(dfs(1)) r = mid;
		else l = mid;
	}
	printf("%.7lf\n", l);
	return 0;
}

CodeForces 1060E

明显的如果两个节点之间的距离是个奇数odd,新图中的距离就是odd / 2 + 1, 是偶数even就是even / 2,那么想一下,将a, b两点间距离表示为dep[a] + dep[b] - 2 * dep[lca(a, b)],因为2 * dep[lca(a, b)]是个偶数,所以只有dep[a], dep[b]中的一个是奇数,一个是偶数时它们之间的距离才是奇数

原图中的答案可以对每条边分别考虑贡献(类似于hdu6446)来求解,将答案乘2,加上距离为奇数的点对数再除以2就是新图中的答案,距离为奇数的点对就是dep为奇数的点数 * dep为偶数的点数

#include <bits/stdc++.h>
#define LL long long
#define db double
using namespace std;

const int MAXN = 200200;
const int MAXE = 400400;
const int INF = 0x3f3f3f3f;

template<typename T> inline void CheckMax(T &A, T B) {
    A < B ? A = B : A;
}

template<typename T> inline void CheckMin(T &A, T B) {
    A > B ? A = B : A;
}

template <typename T> inline void read(T &x) {
    int c = getchar();
    bool f = false;
    for (x = 0; !isdigit(c); c = getchar()) {
        if (c == '-') {
            f = true;
        }
    }
    for (; isdigit(c); c = getchar()) {
        x = x * 10 + c - '0';
    }
    if (f) {
        x = -x;
    }
}

int n;
struct Edge {
    int to, nxt;
    Edge() {}
    Edge(int _to, int _nxt) : to(_to), nxt(_nxt){}
}E[MAXE];

int h[MAXN], cnt, dep[MAXN], fa[MAXN];
LL sz[MAXN], col[2];
LL ans;

inline void add_edge(int u, int v) {
    E[++cnt] = Edge(v, h[u]), h[u] = cnt;
    E[++cnt] = Edge(u, h[v]), h[v] = cnt;
}

void dfs(int x) {
    dep[x] = dep[fa[x]] + 1, sz[x] = 1;
    for(int i = h[x]; i; i = E[i].nxt) {
        int v = E[i].to;
        if(v == fa[x]) continue;
        fa[v] = x;
        dfs(v);
        sz[x] += sz[v];
    }
}

signed main() {
    read(n);
    dep[0] = -1;
    for(int i = 1; i < n; i++) {
        int a, b;
        read(a), read(b);
        add_edge(a, b);
    }
    dfs(1);
    for(int i = 1; i <= n; i++) {
        ans += sz[i] * (n - sz[i]);
        col[dep[i] & 1] ++;
    }
    ans = ((ans + col[1] * (col[0])) >> 1);
    printf("%I64d\n", ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37666409/article/details/83187722