版权声明:博主是菜鸡,但转的时候还是说一声吧 https://blog.csdn.net/qq_37666409/article/details/83187722
手画几步就发现规律了,操作奇数次就是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;
}
考虑将问题变成将两边的数插入到中间来排序
明显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;
}
有点毒
一看求最大最小,二分答案!
然后就想这个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;
}
明显的如果两个节点之间的距离是个奇数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;
}