NOIP模拟5
战争
非常的题,我不会用 所以连暴力都没打出来,后来请教了后就用暴力过了
发现于是直接暴力枚举每个关键点是否选。
首先没有关键点的岛屿内肯定是随机选一个,于是我们先给每个岛屿随机选一个,然后在后来的搜索中用关键点替换,用来判断每个点是否合法,是否可以选。我们只考虑关键点,如果两个点互相有冲突就连边,如果要加入的点与所有已选的点都有连边就是合法的。对于有关键点的岛屿我们提前选了一个非关键点,所以第一次选这个岛屿的时候要先把非关键点去掉。然而对于的子任务会几个,因为选这种关键点肯定不会使答案更优,所以我们能不选就不选,所以加一个特判如果岛屿内还选了其他非关键点就直接跳过
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<bitset>
using namespace std;
#define Miuna printf ("dai suki...")
#define mizuki signed
#define love (1209 & 322 & 901)
namespace LRH
{
template <typename Shiodome_miuna> inline void in (Shiodome_miuna &x)
{
x = 0; char ch, f = 0;
while (!isdigit (ch = getchar ())) if (ch == '-') f = 1;
do
{
x = (x << 1) + (x << 3) + (ch ^ 48);
} while (isdigit (ch = getchar ()));
if (f) x = -x;
}
int stk[40], tp;
template <typename Shiodome_miuna> inline void ot (Shiodome_miuna x, int f = 2)
{
if (x < 0) putchar ('-'), x = -x;
do
{
stk[++ tp] = x % 10;
x /= 10;
} while (x);
while (tp) putchar (stk[tp --] | 48);
if (f == 1) putchar ('\n');
if (!f) putchar (' ');
}
}using namespace LRH;
typedef long long ll;
const int maxn = 1e5 + 10;
int n, m, k, ans, tot, fl = 1;
int c[maxn];
int id[45], p[maxn], u[25], v[25];
bool vis[maxn];
vector <int> g[maxn];
bitset <45> s[45], res;
void dfs (int x, int sum)
{
if (ans < sum) ans = sum, res = s[0];
if (sum + tot - x + 1 <= ans) return;
if (vis[c[id[x]]] && fl) {dfs (x + 1, sum); return;}
if ((s[0] & s[x]) == s[0])
{
s[0][x] = 1;
if (vis[c[id[x]]]) vis[c[id[x]]] = 0, dfs (x + 1, sum), vis[c[id[x]]] = 1;
else dfs (x + 1, sum + 1);
s[0][x] = 0;
}
dfs (x + 1, sum);
}
mizuki main ()
{
freopen ("war.in", "r", stdin);
freopen ("war.out", "w", stdout);
in (m), in (n);
for (int i = 1; i <= n; ++ i) in (c[i]), g[c[i]].push_back (i);
in (k);
for (int i = 1; i <= k; ++ i)
{
in (u[i]), in (v[i]);
if (!p[u[i]]) id[++ tot] = u[i], p[u[i]] = tot;
if (!p[v[i]]) id[++ tot] = v[i], p[v[i]] = tot;
if (c[u[i]] == c[v[i]]) fl = 0;
}
for (int i = 1; i <= m; ++ i) for (auto J : g[i]) if (!p[J])
{
vis[i] = 1;
ans ++;
break;
}
for (int i = 1; i <= tot; ++ i) for (int J = 1; J <= tot; ++ J) if (c[id[i]] != c[id[J]]) s[i][J] = 1;
for (int i = 1; i <= k; ++ i)
{
if (c[u[i]] == c[v[i]]) s[p[u[i]]][p[v[i]]] = s[p[v[i]]][p[u[i]]] = 1;
else s[p[u[i]]][p[v[i]]] = s[p[v[i]]][p[u[i]]] = 0;
}
dfs (1, ans);
ot (ans, 1);
for (int i = res._Find_first (); i != 45; i = res._Find_next (i)) ot (id[i], 0), vis[c[id[i]]] = 0;
for (int i = 1; i <= m; ++ i) if (vis[i]) for (auto J : g[i]) if (!p[J])
{
ot (J, 0);
break;
}
return love;
}
肥胖
由于我们要走的路肯定是越大越好,所以我们直接建出一个重构树,每两个点之间的瓶颈就是他们的,于是直接考虑树形,我们肯定是先吃完一棵子树再去吃另一棵子树,于是就设表示吃完这棵子树最大的初始宽度。
于是就可以转移了,重构树是一个二叉树,如果当前节点的宽度是, 左儿子是, 右儿子是,表示的子树内的糖果的总和,那么就是,于是直接搞就彳亍了
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define Miuna printf ("dai suki...")
#define mizuki signed
#define love (1209 & 322 & 901)
namespace LRH
{
template <typename Shiodome_miuna> inline void in (Shiodome_miuna &x)
{
x = 0; char ch, f = 0;
while (!isdigit (ch = getchar ())) if (ch == '-') f = 1;
do
{
x = (x << 1) + (x << 3) + (ch ^ 48);
} while (isdigit (ch = getchar ()));
if (f) x = -x;
}
int stk[40], tp;
template <typename Shiodome_miuna> inline void ot (Shiodome_miuna x, int f = 2)
{
if (x < 0) putchar ('-'), x = -x;
do
{
stk[++ tp] = x % 10;
x /= 10;
} while (x);
while (tp) putchar (stk[tp --] | 48);
if (f == 1) putchar ('\n');
if (!f) putchar (' ');
}
}using namespace LRH;
typedef long long ll;
const int maxn = 2e5 + 10;
#define int ll
int n, m;
int a[maxn], s[maxn], g[maxn], w[maxn];
struct Shiodome
{
int x, y, w;
friend bool operator < (Shiodome a, Shiodome b)
{
return a.w > b.w;
}
}E[maxn];
int fa[maxn], t;
inline int fd (int x)
{
while (x != fa[x]) x = fa[x] = fa[fa[x]];
return x;
}
struct miuna
{
int v, nt;
}e[maxn << 1];
int tot, head[maxn];
inline void add (int u, int v)
{
e[++ tot] = {v, head[u]};
head[u] = tot;
}
void dfs (int x, int f)
{
s[x] = a[x];
int p1 = 0, p2 = 0;
for (int i = head[x]; i; i = e[i].nt)
{
int y = e[i].v;
if (y == f) continue;
dfs (y, x);
s[x] += s[y];
if (!p1) p1 = y;
else p2 = y;
}
if (!w[x]) return;
g[x] = max (min (w[x] - s[p1], g[p2] - s[p1]), min (w[x] - s[p2], g[p1] - s[p2]));
}
mizuki main ()
{
freopen ("fat.in", "r", stdin);
freopen ("fat.out", "w", stdout);
in (n), in (m);
for (int i = 1; i <= n; ++ i) in (a[i]);
for (int i = 1; i <= m; ++ i) in (E[i].x), in (E[i].y), in (E[i].w);
sort (E + 1, E + 1 + m);
for (int i = 1; i <= n; ++ i) fa[i] = i;
t = n;
for (int i = 1; i <= m; ++ i)
{
int fx = fd (E[i].x), fy = fd (E[i].y);
if (fx != fy)
{
t ++;
fa[t] = t;
fa[fx] = fa[fy] = t;
w[t] = E[i].w;
add (t, fx), add (t, fy);
}
}
memset (g, 127, sizeof (g));
dfs (t, 0);
if (g[t] <= 0) puts ("-1");
else ot (g[t]);
return love;
}
分摊
这题真的是得不彳亍,每个节点都是好父亲,一拿到钱都会先给儿子分,于是根据它们的操作我们可以发现就是依次填满需求最小的一个儿子,(现在这个需求指的是发给儿子后还能刚好满足自己的钱数,即),其他儿子也获得相应的钱,于是我们就可以获得暴力思路,每个点想要满足需求,那么他的父亲就需要获得,为一个点的需求,是他的兄弟节点,直接每次往上跳父亲扫兄弟就可以。
然而暴力不能体现一个优秀的基本素养,我们考虑优化暴力,发现如果一个点的需求总是比兄弟节点的都要大,那么每次计算都是直接加上他的兄弟的,而且这种情况很容易出现,于是我们就可以考虑倍增,先预处理出来兄弟节点的的前缀和,并预处理出向上跳个父亲一直是最大值该点的需求最小是多少,那么向上跳一个父亲显然是兄弟的最大值,跳个就是,这个是向上跳个父亲如果一直是最大值会加多少,于是就可以直接倍增计算每个点了
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define Miuna printf ("dai suki...")
#define mizuki signed
#define love (1209 & 322 & 901)
namespace LRH
{
template <typename Shiodome_miuna> inline void in (Shiodome_miuna &x)
{
x = 0; char ch, f = 0;
while (!isdigit (ch = getchar ())) if (ch == '-') f = 1;
do
{
x = (x << 1) + (x << 3) + (ch ^ 48);
} while (isdigit (ch = getchar ()));
if (f) x = -x;
}
int stk[40], tp;
template <typename Shiodome_miuna> inline void ot (Shiodome_miuna x, int f = 2)
{
if (x < 0) putchar ('-'), x = -x;
do
{
stk[++ tp] = x % 10;
x /= 10;
} while (x);
while (tp) putchar (stk[tp --] | 48);
if (f == 1) putchar ('\n');
if (!f) putchar (' ');
}
}using namespace LRH;
typedef long long ll;
const int maxn = 3e5 + 10;
int n, m;
struct miuna
{
int v, nt;
}e[maxn];
int tot, head[maxn];
inline void add (int u, int v)
{
e[++ tot] = {v, head[u]};
head[u] = tot;
}
vector <ll> vec[maxn], s[maxn];
int fa[maxn][23];
ll sum[maxn][23], f[maxn][23];
ll siz[maxn];
void dfs (int x)
{
for (int i = 1; i <= 20; ++ i) fa[x][i] = fa[fa[x][i - 1]][i - 1];
for (int i = head[x]; i; i = e[i].nt)
{
int y = e[i].v;
dfs (y);
siz[x] += siz[y];
}
}
void exdfs (int x)
{
if (x)
{
if (vec[fa[x][0]].size () == 1) f[x][0] = 0;
else
{
int pos = vec[fa[x][0]].size () - 1;
if (siz[x] == vec[fa[x][0]][pos]) pos --;
f[x][0] = vec[fa[x][0]][pos];
}
sum[x][0] = s[fa[x][0]][s[fa[x][0]].size () - 1] - siz[x];
for (int i = 1; i <= 20; ++ i)
{
sum[x][i] = sum[x][i - 1] + sum[fa[x][i - 1]][i - 1];
f[x][i] = max (f[x][i - 1], f[fa[x][i - 1]][i - 1] - sum[x][i - 1]);
}
}
for (int i = head[x]; i; i = e[i].nt) exdfs (e[i].v);
}
void work (int x)
{
ll tmp = siz[x];
while (x)
{
for (int i = 20; i >= 0; -- i)
{
if (x && tmp >= f[x][i])
{
tmp += sum[x][i];
x = fa[x][i];
}
}
if (x)
{
int pos = upper_bound (vec[fa[x][0]].begin (), vec[fa[x][0]].end (), tmp) - vec[fa[x][0]].begin () - 1;
ll t = tmp;
if (pos < 0) tmp += t * vec[fa[x][0]].size () - min (siz[x], t);
else
{
tmp += t * (s[fa[x][0]].size () - pos - 1);
tmp += s[fa[x][0]][pos];
tmp -= min (siz[x], t);
}
x = fa[x][0];
}
}
ot (tmp, 1);
}
mizuki main ()
{
freopen ("share.in", "r", stdin);
freopen ("share.out", "w", stdout);
in (n);
for (int i = 1; i <= n; ++ i) in (fa[i][0]), in (siz[i]), add (fa[i][0], i);
dfs (0);
for (int i = 1; i <= n; ++ i) vec[fa[i][0]].push_back (siz[i]), s[fa[i][0]].push_back (0);
for (int i = 0; i <= n; ++ i)
{
if (!vec[i].size ()) continue;
sort (vec[i].begin (), vec[i].end ());
s[i][0] = vec[i][0];
for (int J = 1; J < (int) vec[i].size (); ++ J)
s[i][J] = s[i][J - 1] + vec[i][J];
}
exdfs (0);
for (int i = 1; i <= n; ++ i) work (i);
return love;
}
修路
还没有来得及改,然而可学长博客去看
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?