历程

被暴打了

原因是钻进了 \(T4\) 的坑中。。。

先看完题,发现 \(T4\) 比较有意思,\(T2\) 没有想法

\(T3\) 挺容易,做法似乎很好想

\(T1\) 送分,十几分钟搞定

然后开 \(T4\),推了一下,明白题目需要我们干的事情

开码,发现修改与标记有些烦,然后标记打错了,一直调到 \(11\) 点

疯了!

还有 \(\text{45 min}\),只要忍痛弃了

看看 \(T3\),很好做,\(5 min\) 打完

有充满自信,放弃 \(T2\) 部分分,继续调 \(T4\)

但始终没有意识到一处标记的问题

导致比赛结束被暴打(更重要的是,暴力每题普遍 \(80,90pts\) !!神仙数据。。。)

\(\text{T1 1782. Travel}\)

这不 \(Floyd\) 预处理后分层最短路 \(spfa\) 啊!

正好复习最短路模板

$\text{Code}$

\(\text{Code}\)

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#define RE register
using namespace std; const int N = 105, INF = 0x3f3f3f3f;
int n, m, q, G[N][N], vis[N][N], bz[N][15], f[N][15];
struct node{int x, k;};
queue<node> Q; void SPFA()
{
memset(f, INF, sizeof f), Q.push(node{1, 0}), f[1][0] = 0, bz[1][0] = 1;
while (!Q.empty())
{
node z = Q.front(); Q.pop();
for(RE int i = 1; i <= n; i++)
if (vis[z.x][i] && i ^ z.x)
{
int j = i, k = z.k, w = G[z.x][i];
if (!vis[i][z.x]) w *= 2, ++k;
if (k <= q && f[j][k] > f[z.x][z.k] + w)
{
f[j][k] = f[z.x][z.k] + w;
if (!bz[j][k]) Q.push(node{j, k}), bz[j][k] = 1;
}
}
bz[z.x][z.k] = 0;
}
} int main()
{
scanf("%d%d%d", &n, &m, &q), memset(G, INF, sizeof G);
for(RE int i = 1, x, y, z; i <= m; i++)
scanf("%d%d%d", &x, &y, &z), G[x][y] = min(G[x][y], z), vis[x][y] = 1;
for(RE int k = 1; k <= n; k++)
for(RE int i = 1; i <= n; i++)
if (i ^ k)
for(RE int j = 1; j <= n; j++)
if (j ^ i && j ^ k)
vis[i][j] = (vis[i][j] | (vis[i][k] && vis[k][j]));
SPFA();
int ans = INF;
for(RE int i = 1; i <= q; i++) ans = min(ans, f[n][i]);
if (ans == INF) ans = -1;
printf("%d\n", ans);
}

\(\text{T2 3337. wyl8899的TLE}\)

思考答案的产生

从 \(A\) 的首位, \(B\) 的某个位置开始,求 \(LCP\)

然后魔法地同时跳过一格(计入贡献),再求 \(LCP\)

答案取最大值即可

也就是说可以枚举 \(B\) 的开始位置,二分加哈希求 \(LCP\) 即可

思维真不高。。。

也算复习字符串基操吧

$\text{Code}$

\(\text{Code}\)

#include <cstdio>
#include <cstring>
#include <iostream>
#define RE register
#define IN inline
using namespace std;
typedef long long LL; const int N = 5e4 + 5, P1 = 1e9 + 7, P2 = 1e9 + 9, B = 29;
char s1[N], s2[N];
LL b1[N], b2[N]; struct Hash{
int n; LL p1[N], p2[N];
IN void init(char *s)
{
n = strlen(s + 1);
for(RE int i = 1; i <= n; i++)
p1[i] = (p1[i - 1] * B + s[i] - 'a') % P1, p2[i] = (p2[i - 1] * B + s[i] - 'a') % P2;
}
IN int get1(int l, int r){return (p1[r] - p1[l - 1] * b1[r - l + 1] % P1 + P1) % P1;}
IN int get2(int l, int r){return (p2[r] - p2[l - 1] * b2[r - l + 1] % P2 + P2) % P2;}
}h1, h2; IN int lcp(int l1, int l2)
{
int l = 0, r = min(h1.n - l1 + 1, h2.n - l2 + 1), mid = l + r >> 1, res = 0;
for(; l <= r; mid = l + r >> 1)
if ((h1.get1(l1, l1 + mid - 1) == h2.get1(l2, l2 + mid - 1))
&& (h1.get2(l1, l1 + mid - 1) == h2.get2(l2, l2 + mid - 1))) res = mid, l = mid + 1;
else r = mid - 1;
return res;
} int main()
{
b1[0] = b2[0] = 1;
for(RE int i = 1; i <= N - 3; i++) b1[i] = b1[i - 1] * B % P1, b2[i] = b2[i - 1] * B % P2;
scanf("%s%s", s1 + 1, s2 + 1), h1.init(s1), h2.init(s2);
int ans = 0;
for(RE int i = 1, len; i <= h2.n; i++)
ans = max(ans, (len = lcp(1, i)) + lcp(len + 2, i + len + 1) + (len < h1.n && i + len - 1 < h2.n));
printf("%d\n", ans);
}

\(\text{T3 3338. 法法塔的奖励}\)

考虑一个点的答案,显然由子树符合条件的 \(dp\) 值转来

发现是维护子树的问题,所以树上启发式合并加树状数组做到 \(O(n\log^2 n)\) 或者线段树合并做到 \(O(n\log n)\)

当然是打前者啦,跟打暴力一样一样的

$\text{Code}$

\(\text{Code}\)

#include <cstdio>
#include <iostream>
#define RE register
#define IN inline
using namespace std; const int N = 1e5 + 5;
int n, fa[N], a[N], h[N], tot, c[N];
int dfc, siz[N], dfn[N], rev[N], son[N], ans[N];
struct edge{int to, nxt;}e[N];
IN void add(int x, int y){e[++tot] = edge{y, h[x]}, h[x] = tot;} void dfs1(int x)
{
siz[x] = 1, dfn[x] = ++dfc, rev[dfc] = x;
for(RE int i = h[x]; i; i = e[i].nxt)
{
int v = e[i].to;
dfs1(v), siz[x] += siz[v];
if (siz[v] > siz[son[x]]) son[x] = v;
}
} IN int lowbit(int x){return x & (-x);}
IN void update(int x, int v){for(; x <= n; x += lowbit(x)) c[x] = max(c[x], v);}
IN void clear(int x){for(; x <= n; x += lowbit(x)) c[x] = 0;}
IN int query(int x)
{
int res = 0;
for(; x; x -= lowbit(x)) res = max(res, c[x]);
return res;
} void dfs2(int x, int kp)
{
for(RE int i = h[x]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v == son[x]) continue;
dfs2(v, 0);
}
if (son[x]) dfs2(son[x], 1);
for(RE int i = h[x]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v == son[x]){update(a[son[x]], ans[son[x]]); continue;}
for(RE int j = dfn[v]; j <= dfn[v] + siz[v] - 1; j++) update(a[rev[j]], ans[rev[j]]);
}
ans[x] = query(a[x]) + 1;
if (!kp) for(RE int i = dfn[x] + 1; i <= dfn[x] + siz[x] - 1; i++) clear(a[rev[i]]);
} int main()
{
scanf("%d", &n); int x; scanf("%d", &x);
for(RE int i = 2; i <= n; i++) scanf("%d", &fa[i]), add(fa[i], i);
for(RE int i = 1; i <= n; i++) scanf("%d", &a[i]);
dfs1(1), dfs2(1, 1);
for(RE int i = 1; i <= n; i++) printf("%d ", ans[i]);
}

\(\text{T4 3339. wyl8899和法法塔的游戏}\)

很容易想到 \(nim\) 游戏的结论:异或和为零为先手必败态

那么先求异或和,需要第一步取完后留给对手必败态,即 \((a_r-x) \oplus \text{others} = 0\)

需 \(x=a_r-\text{others}\) 最大化,可持久化 \(Trie\) 即可

但是需要支持修改操作,所以考虑分块加 \(Trie\)

注意打标记时的细节

$\text{Code}$

\(\text{Code}\)

#include <cstdio>
#include <cmath>
#include <iostream>
#define IN inline
#define RE register
using namespace std; const int N = 1e5 + 5, B = 319;
int n, m; struct DS{
int pos[N], block, a[N], tag[B], tr[N * 20][2], size, sum[N * 20], rt[B];
IN void init()
{
block = sqrt(n);
for(RE int i = 1; i <= n; i++) pos[i] = (i - 1) / block + 1;
}
IN void update(int p, int x, int v)
{
if (!rt[p]) rt[p] = ++size;
int u = rt[p];
for(RE int i = 10; i >= 0; i--)
{
int ch = (x >> i) & 1;
if (!tr[u][ch]) tr[u][ch] = ++size;
sum[u = tr[u][ch]] += v;
}
}
IN int query(int p, int v)
{
int u = rt[p], res = 0;
for(RE int i = 10; i >= 0; i--)
{
int ch = (v >> i) & 1;
if (sum[tr[u][ch]]) u = tr[u][ch];
else if (sum[tr[u][ch ^ 1]]) u = tr[u][ch ^ 1], res |= (1 << i);
}
return res;
}
IN int get(int x){return a[x] ^ tag[pos[x]] ^ a[x + 1] ^ tag[pos[x + 1]];}
IN void Modify(int r, int v)
{
int t = get(r), w = a[r] ^ (t - v) ^ tag[pos[r]] ^ a[r + 1] ^ tag[pos[r + 1]];
for(RE int i = r; i >= (pos[r] - 1) * block + 1; i--)
update(pos[r], a[i], -1), update(pos[r], a[i] ^= w, 1);
for(RE int i = 1; i < pos[r]; i++) tag[i] ^= w;
}
IN int Query(int l, int r, int v)
{
int res = N;
for(RE int i = l; i <= min(pos[l] * block, r); i++) res = min(res, a[i] ^ tag[pos[l]] ^ v);
if (pos[l] ^ pos[r])
for(RE int i = (pos[r] - 1) * block + 1; i <= r; i++) res = min(res, a[i] ^ tag[pos[r]] ^ v);
for(RE int i = pos[l] + 1; i < pos[r]; i++) res = min(res, query(i, v ^ tag[i]));
return res;
}
}T; int main()
{
scanf("%d", &n);
for(RE int i = 1; i <= n; i++) scanf("%d", &T.a[i]);
T.init();
for(RE int i = n; i; i--) T.a[i] ^= T.a[i + 1], T.update(T.pos[i], T.a[i], 1);
scanf("%d", &m);
for(RE int i = 1, ed, L, R; i <= m; i++)
{
scanf("%d%d%d", &ed, &L, &R);
int ans = T.get(ed) - T.Query(L, R, T.a[ed] ^ T.tag[T.pos[ed]]);
if (ans <= 0) ans = -1;
if (ans != -1) T.Modify(ed, ans);
printf("%d\n", ans);
}
}

可见这套题挺简单的,但是考场要分配好时间,避免陷入一处坑很久导致意外或者“正常”死亡

JZOJ 2022.07.06【提高组A】模拟的更多相关文章

  1. 2018.12.30【NOIP提高组】模拟赛C组总结

    2018.12.30[NOIP提高组]模拟赛C组总结 今天成功回归开始做比赛 感觉十分良(zhōng)好(chà). 统计数字(count.pas/c/cpp) 字符串的展开(expand.pas/c ...

  2. 2018.12.08【NOIP提高组】模拟B组总结(未完成)

    2018.12.08[NOIP提高组]模拟B组总结 diyiti 保留道路 进化序列 B diyiti Description 给定n 根直的木棍,要从中选出6 根木棍,满足:能用这6 根木棍拼出一个 ...

  3. JZOJ 5185. 【NOIP2017提高组模拟6.30】tty's sequence

    5185. [NOIP2017提高组模拟6.30]tty's sequence (Standard IO) Time Limits: 1000 ms  Memory Limits: 262144 KB ...

  4. JZOJ 5196. 【NOIP2017提高组模拟7.3】B

    5196. [NOIP2017提高组模拟7.3]B Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed Limits   Goto Pro ...

  5. JZOJ 5197. 【NOIP2017提高组模拟7.3】C

    5197. [NOIP2017提高组模拟7.3]C Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed Limits   Goto Pro ...

  6. JZOJ 5195. 【NOIP2017提高组模拟7.3】A

    5195. [NOIP2017提高组模拟7.3]A Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed Limits   Goto Pro ...

  7. JZOJ 5184. 【NOIP2017提高组模拟6.29】Gift

    5184. [NOIP2017提高组模拟6.29]Gift (Standard IO) Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed ...

  8. Vigenère密码 2012年NOIP全国联赛提高组(字符串模拟)

    P1079 Vigenère 密码 题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简 ...

  9. 等价表达式 2005年NOIP全国联赛提高组(栈模拟)

    P1054 等价表达式 题目描述 明明进了中学之后,学到了代数表达式.有一天,他碰到一个很麻烦的选择题.这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的 ...

  10. 2017.07.06【NOIP提高组】模拟赛B组

    Summary 今天比赛感觉题目很奇葩,都可以用许多简单方法来做,正确性都显然,当然也有点水,也就是说是考我们的数感和数学知识,而程序,只是代码的体现. 这次的时间安排感觉不错,因为很快就打完最后一道 ...

随机推荐

  1. 痞子衡嵌入式:MCUXpresso IDE下高度灵活的FreeMarker链接文件模板机制

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是MCUXpresso IDE下高度灵活的FreeMarker链接文件模板机制. 痞子衡之前写过一篇文章 <MCUXpresso I ...

  2. 关于windows上pip安装报错

    前言 因为我一直用linux,所以windows上的很多问题我都不怎么记录了,但是昨天去网吧,打算玩玩,遇到了安装第三方库报错,所以我有必要水一篇文章 为什么报错 其实python的第三方库很多不仅仅 ...

  3. linux配置 python 开发环境sublime text及一些使用心得

    前言 一直以来我都使用 sublime text 作为主流开发的 ide ,但其实我开始在我的 linux mint 系统使用 sublime text 配置 python3 的开发环境踩过的坑又何止 ...

  4. label studio 结合 MMDetection 实现数据集自动标记、模型迭代训练的闭环

    前言 一个 AI 方向的朋友因为标数据集发了篇 SCI 论文,看着他标了两个多月的数据集这么辛苦,就想着人工智能都能站在围棋巅峰了,难道不能动动小手为自己标数据吗?查了一下还真有一些能够满足此需求的框 ...

  5. mybatis sql批量插入

    insert into jrqf_officialcard (id, budget_unit, money_purpose, economic_type, money, func_subject_na ...

  6. 关于 risrqnis

    这道题里最有用的( Range Insert Subset Range Query [n?] In Set 破案了 我那五个点是因为维护不知道有什么用的东西炸了 删了就过了 题面 [JRKSJ R4] ...

  7. 深入浅出Seata的AT模式

    目录 一.业务背景 二.Seata架构 1.核心组件 2.AT模式 三.案例分析 1.流程分析 2.写隔离 3.读隔离 四.对比XA模式 五.参考源码 单个掉队,导致集体被动摆烂: 一.业务背景 在分 ...

  8. 在实际应用中联合体union的妙用

    关键字union,又称为联合体.共用体,联合体的声明和结构体类似,但是它的行为方式又和结构体不同,这里的行为方式主要指的是其在内存中的体现,结构体中的成员每一个占据不同的内存空间,而联合体中的所有成员 ...

  9. Doris安装部署

    下载安装 Doris运行在Linux环境中,推荐 CentOS 7.x 或者 Ubuntu 16.04 以上版本,同时你需要安装 Java 运行环境(JDK最低版本要求是8) 1.下载安装包 下载地址 ...

  10. .NET周报【12月第1期 2022-12-08】

    国内文章 CAP 7.0 版本发布通告 - 支持延迟消息,性能炸了? https://www.cnblogs.com/savorboard/p/cap-7-0.html) 今天,我们很高兴宣布 CAP ...