\(T1\)

题目描述

在仙界中有着 \(n\) 位神仙, 每位神仙用一个 \(1 ∼ n\) 的特异编号表示, 老祖 \(ChitongZ\) 的编号为 \(1\) .

除去至尊至圣, 统管仙界的老祖 \(ChitongZ\) 外, 其他的 \(n − 1\) 位神仙都有唯一的尊师, 并且形成了一个树形结构.

老祖 \(ChitongZ\) 为了提升仙界综合实力, 倡导神仙们进行修炼.

但每次修炼是需要一颗金丹的, 若一位神仙自己没有金丹, 就需要向自己的尊师索取一颗. 若尊师也没有, 则尊师会向他的尊师索取一颗, 以此类推, 直到索取到一颗金丹, 修炼结束后这颗金丹就会被消耗掉.

\(Solution\)

预估 \(100pts\) ,数组开小了只有 \(60pts\)

其实这道题很多做法,我想了两个,都记录一下

\(EP.1\)

类似树剖,先做一个 \(dfs\) ,给每个点标上 \(dfs\) 序 \(id[x]\),用线段树维护覆盖

对于一个点 \(x\) ,离它最近的被标记的点(即 \(ans\))是 所有可以覆盖它的点中 \(id\) 最大的,所以在每次线段树做 \(pushdown\) 的时候取 \(max\) ,输出的时候再转化为原答案

\(EP.2\)

用并查集维护

把所有操作保存下来,构造出一颗树,树的状态为所有操作完成后,再做一个 \(dfs\) ,若点 \(x\) 被标记过,则 \(s[x] = x\) ,不然指向 \(fa[x]\)

然后倒着操作,即给一个点标记变为去掉一个点的标记,若这个点没有标记了,则把 \(s[x]\) 指向 \(fa[x]\)

Code

只有 \(EP.2\) 的代码233

#include<bits/stdc++.h>
#define ll long long
#define F(i, x, y) for(int i = x; i <= y; ++ i)
using namespace std;
int read();
const int N = 5e6 + 5;
const ll B1 = 37;
const ll P1 = 19260817;
const ll B2 = 137;
const ll P2 = 998244353;
int n, m, x;
int s[N], d[N], fa[N], k[N];
ll ans1, ans2;
struct kk{
int edge;
char sta;
}Q[N];
int head[N], cnt;
struct node{
int ver, next;
}a[N << 1];
void add(int x, int y)
{
++ cnt;
a[cnt].ver = y, a[cnt].next = head[x], head[x] = cnt;
}
void dfs(int x, int f)
{
s[x] = d[x] ? x : f, fa[x] = f;
for(int i = head[x]; i; i = a[i].next)
if(a[i].ver != f)
dfs(a[i].ver, x);
}
int search(int x)
{
return x == s[x] ? x : s[x] = search(s[x]);
}
int main()
{
freopen("decomposition.in","r",stdin);
freopen("decomposition.out","w",stdout);
n = read(), m = read();
F(i, 2, n) x = read(), add(x, i), add(i, x);
F(i, 1, m)
{
Q[i].sta = read(), Q[i].edge = read();
if(Q[i].sta == 2) ++ d[Q[i].edge];
}
dfs(1, 0), s[1] = 1, fa[1] = 1;
for(int i = m; i >= 1; -- i)
{
if(Q[i].sta == 1) k[i] = search(Q[i].edge);
else
{
-- d[Q[i].edge];
if(! d[Q[i].edge]) s[Q[i].edge] = fa[Q[i].edge];
}
}
F(i, 1, m) if(k[i])
ans1 = (ans1 * B1 + k[i]) % P1, ans2 = (ans2 * B2 + k[i]) % P2;
printf("%lld %lld", ans1, ans2);
return 0;
}
int read()
{
int x = 0;
char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x;
}

\(T2\)

题目描述

有 \(n\) 个人依次进入观影厅, 观看 \(Weathering \ with \ You\) .

观影厅只有一排座位, 第 \(1\) 个人进入时, 会选择第 \(1\) 个座位坐下.

由于观影厅空调坏掉了, 十分炎热, 之后的每个人进入时, 他会选择一个离最近的已经坐下的人尽可能远的空位.

如果有多个空位使得离最近的人同样远, 则他会从其中随机选取一个.

若有两个人选择的位置相邻, 他们就会不满意.

为了让所有人都满意, 观影厅至少需要有几个座位呢?

\(Solution\)

根据各种打表找规律可得出

\[f(x) = x + 2^{1+⌊log_2(x−2)⌋}.
\]

然后用高精度写

比较方便的写法是,用 \(2\) 不断往上乘,一边乘一边判断大小,最后加一个 \(n\)

这样就只要写高精乘低精,判断大小,高精度加法,比较好写

还有特殊情况,\(f(1) = 1\) ,\(f(2) = 3\),我没想到然后就只有 \(95pts\)

Code

#include<bits/stdc++.h>
#define F(i, x, y) for(int i = x; i <= y; ++ i)
using namespace std;
int read();
const int N = 2e3 + 5;
char z;
int a[N], alen;
int b[N], blen;
int c[N], clen;
void mul(int b[])
{
int x = 0;
F(i, 1, blen) x += b[i] * 2, b[i] = x % 10, x = x / 10;
if(x) b[++ blen] = x;
}
bool comp(int a[], int b[])
{
int x = 2, clen = blen;
F(i, 1, blen) c[i] = b[i];
F(i, 1, clen)
{
c[i] += x, x = c[i] / 10, c[i] %= 10;
if(! x) break;
}
if(x) c[++ clen] = x;
if(alen != clen) return alen > clen;
for(int i = alen; i >= 1; -- i)
if(a[i] != c[i]) return a[i] > c[i];
return true;
}
int main()
{
freopen("tenki.in","r",stdin);
freopen("tenki.out","w",stdout);
while(scanf("%c", &z) != EOF) c[++ alen] = z - '0';
-- alen;
F(i, 1, alen) a[alen - i + 1] = c[i];
if(alen == 1 && (a[1] == 1 || a[1] == 2))
{
puts(a[1] == 1 ? "1" : "3");
return 0;
}
blen = 1, b[blen] = 2;
while(comp(a, b)) mul(b);
memset(c, 0, sizeof(c));
F(i, 1, max(alen, blen))
{
c[i] = c[i] + a[i] + b[i];
c[i + 1] = c[i] / 10, c[i] %= 10;
}
clen = max(alen, blen);
if(c[clen + 1]) ++ clen;
for(int i = clen; i >= 1; -- i) printf("%d", c[i]);
return 0;
}
/*
q = (log2 (n - 2)) + 1;
ans = 2 ^ q + n;
*/

\(T3\)

题目描述

给定一个正整数 \(k\) , 以及一棵 \(n\) 个节点的以 \(1\) 为根的有根树, 边有长度.

记 \(LCA(a, b)\) 表示 \(a\) 与 \(b\) 在树上的最近公共祖先, \(dist(a)\) 表示树根到 \(a\) 的距离.

每个节点可以是黑色或白色, 初始时每个节点的颜色为白色.

进行 m 次操作, 每次操作是以下两种形式之一:

修改操作: 给出一个修改节点 \(x\) , 将节点 \(x\) 染上黑色. 保证 \(x\) 在染色前为白色.

询问操作: 给出一个询问节点 \(x\) , 记所有黑点形成的集合为 \(S\) , 求出下面式子的值:

\[\sum_{y∈S}F( dist ( LCA ( x, y ) ) )
\]

其中函数 \(F\) 定义为,

\[F(x) =\sum\limits_{i=1}^xi^k
\]

由于答案可能很大, 只需要输出答案对 \(P = 998244353\) 取模的结果

\(Solution\)

这道题的难点:

\(1.\)题意比较绕,要求的答案函数套函数,很容易弄错

\(2.\)列出式子并把式子化简,将定值和要维护的值拆开

肝了半个下午 \(+\) 半个晚自习,心力交瘁...不过真的是道好题!!

\((btw\),膜一膜 \(xiaolilsq\) 大佬,本来我都没信心把这道题改出来233,结果他讲题讲得好清楚然后就改掉了!\()\)

\(Code\)

#include<bits/stdc++.h>
#define ll long long
#define ls k << 1
#define rs (k << 1) + 1
#define mid ((l + r) >> 1)
#define F(i, x, y) for(int i = x; i <= y; ++ i)
using namespace std;
int read();
const int N = 1e5 + 5;
const int M = 1e7 + 5;
const int mod = 998244353;
int n, m, s;
ll x, y, num, vis[N], f[M], dist[N];
ll tree[N << 2], atree[N << 2], tag[N << 2], a[N];
ll dep[N], size[N], fa[N], son[N], id[N], top[N];
ll head[N], cnt, ver[N << 1], edge[N << 1], nxt[N << 1];
void add(int x, int y, int z)
{
ver[++ cnt] = y, edge[cnt] = z, nxt[cnt] = head[x], head[x] = cnt;
}
ll qpower(ll x, int y)
{
ll res = 1;
while(y)
{
if(y & 1) res = res * x % mod;
x = x * x % mod, y >>= 1;
}
return res;
}
void dfs1(int x, int ffa)
{
dep[x] =dep[ffa] + 1, size[x] = 1, fa[x] = ffa;
int maxn = -1;
for(int i = head[x]; i; i = nxt[i])
if(ver[i] != ffa)
{
dist[ver[i]] = dist[x] + edge[i], dfs1(ver[i], x), size[x] += size[ver[i]];
if(size[ver[i]] > maxn) son[x] = ver[i], maxn = size[ver[i]];
}
}
void dfs2(int x, int topfa, int ffa)
{
id[x] = ++ num, top[x] = topfa;
a[id[x]] = (f[dist[x]] - f[dist[ffa]] + mod) % mod;
if(! son[x]) return;
dfs2(son[x], topfa, x);
for(int i = head[x]; i; i = nxt[i])
if(ver[i] != fa[x] && ver[i] != son[x])
dfs2(ver[i], ver[i], x);
}
void pushup(int l, int r, int k)
{
atree[k] = (atree[ls] + atree[rs]) % mod;
}
void build(int l, int r, int k)
{
if(l == r)
{
tree[k] = a[l] % mod;
return;
}
build(l, mid, ls);
build(mid + 1, r, rs);
tree[k] = (tree[ls] + tree[rs]) % mod;
}
void pushdown(int l, int r, int k)
{
if(! tag[k]) return;
atree[ls] = (tree[ls] * tag[k] % mod + atree[ls]) % mod;
atree[rs] = (tree[rs] * tag[k] % mod + atree[rs]) % mod;
tag[ls] += tag[k], tag[rs] += tag[k];
tag[k] = 0;
}
void modify(int l, int r, int k, int x, int y, int v)
{
if(l >= x && r <= y)
{
atree[k] = (tree[k] * v % mod + atree[k]) % mod, tag[k] += v;
return;
}
pushdown(l, r, k);
if(x <= mid) modify(l, mid, ls, x, y, v);
if(y > mid) modify(mid + 1, r, rs, x, y, v);
pushup(l, r, k);
}
ll query(int l, int r, int k, int x, int y)
{
if(l >= x && r <= y) return atree[k];
pushdown(l, r, k);
ll res = 0;
if(x <= mid) res = (res + query(l, mid, ls, x, y)) % mod;
if(y > mid) res = (res + query(mid + 1, r, rs, x, y)) % mod;
return res;
}
void modify_range(int x)
{
if(vis[x]) return;
vis[x] = 1;
while(top[x] != 1)
{
modify(1, n, 1, id[top[x]], id[x], 1);
x = fa[top[x]];
}
modify(1, n, 1, 1, id[x], 1);
}
ll query_range(int x)
{
ll res = 0;
while(top[x] != 1)
{
res = (res + query(1, n, 1, id[top[x]], id[x])) % mod;
x = fa[top[x]];
}
res = (res + query(1, n, 1, 1, id[x])) % mod;
return res;
}
int main()
{
freopen("mafumafu.in","r",stdin);
freopen("mafumafu.out","w",stdout);
n = read(), m = read(), s = read();
F(i, 1, M - 1) f[i] = (f[i - 1] + qpower(i, s) % mod) % mod;
F(i, 2, n) x = read(), y = read(), add(x, i, y), add(i, x, y);
dfs1(1, 0), dfs2(1, 1, 0), build(1, n, 1);
while(m --)
{
y = read(), x = read();
if(y == 1) modify_range(x);
if(y == 2) printf("%lld\n", query_range(x));
}
return 0;
}
int read()
{
int x = 0, f = 1;
char c = getchar();
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}

总结

排名\(:5/17\)

预估分数\(:100 + 100 + 0\)

实际分数\(:60 + 95 + 0\)

\(1.\)都 \(0202\) 了我怎么还犯数组开小了这种错误。。。

\(2.\)都 \(0202\) 了我怎么还反不考虑特殊情况这种错误。。。

总体来说今天还行,调整了考试状态,尽力地拿分,其实写完前两道题后还剩半个小时,打了 \(t3\) 的暴力,可惜没时间调了,不过这种习惯还是要坚持,抓住每一分每一秒;但是还是有一些**错误,爆锤我寄几!!!

【考试总结】欢乐模拟赛_Day2的更多相关文章

  1. 【考试总结】欢乐模拟赛_Day1

    \(T1\) 题目描述 给出一个 \(n × n\) 的, 元素为自然数的矩阵. 这个矩阵有许许多多个子矩阵, 定义它的所有子矩阵形成的集合为 \(S\) . 对于一个矩阵 \(k\) , 定义 \( ...

  2. NOIP欢乐模拟赛 T1 解题报告

    小澳的方阵 (matrix.cpp/c/pas) [题目描述] 小澳最近迷上了考古,他发现秦始皇的兵马俑布局十分有特点,热爱钻研的小澳打算在电脑上还原这个伟大的布局. 他努力钻研,发现秦始皇布置兵马俑 ...

  3. NOIP欢乐模拟赛 T3 解题报告

    3.小澳的葫芦 (calabash.cpp/c/pas) [题目描述] 小澳最喜欢的歌曲就是<葫芦娃>. 一日表演唱歌,他尽了洪荒之力,唱响心中圣歌. 随之,小澳进入了葫芦世界. 葫芦世界 ...

  4. NOIP欢乐模拟赛 T2 解题报告

    小澳的坐标系 (coordinate.cpp/c/pas) [题目描述] 小澳者表也,数学者景也,表动则景随矣. 小澳不喜欢数学,可数学却待小澳如初恋,小澳睡觉的时候也不放过. 小澳的梦境中出现了一个 ...

  5. Test20171009 考试总结 NOIP模拟赛

    题目难度合适,区分度适中,但是本人水平不佳,没有拿到满意的分数. T1(matrix) 一种比较容易想到的想法是枚举起点求出最长全1串做预处理,这是O(n^2)的. 接着枚举列起点,列终点,通过后缀和 ...

  6. NOI模拟赛 Day1

    [考完试不想说话系列] 他们都会做呢QAQ 我毛线也不会呢QAQ 悲伤ING 考试问题: 1.感觉不是很清醒,有点困╯﹏╰ 2.为啥总不按照计划来!!! 3.脑洞在哪里 4.把模拟赛当作真正的比赛,紧 ...

  7. PKUSC 模拟赛 day1 下午总结

    下午到了机房之后又困又饿,还要被强行摁着看英文题,简直差评 第一题是NOIP模拟赛的原题,随便模拟就好啦 本人模拟功力太渣不小心打错了个变量,居然调了40多分钟QAQ #include<cstd ...

  8. [GRYZ]寒假模拟赛

    写在前面 这是首次广饶一中的OIERS自编自导,自出自做(zuo)的模拟赛. 鉴于水平气压比较低,机(wei)智(suo)的WMY/XYD/HYXZC就上网FQ下海找了不少水(fei)题,经过他们优( ...

  9. 10.30 NFLS-NOIP模拟赛 解题报告

    总结:今天去了NOIP模拟赛,其实是几道USACO的经典的题目,第一题和最后一题都有思路,第二题是我一开始写了个spfa,写了一半中途发现应该是矩阵乘法,然后没做完,然后就没有然后了!第二题的暴力都没 ...

随机推荐

  1. OpenCV-Python 特征匹配 + 单应性查找对象 | 四十五

    目标 在本章节中,我们将把calib3d模块中的特征匹配和findHomography混合在一起,以在复杂图像中找到已知对象. 基础 那么我们在上一环节上做了什么?我们使用了queryImage,找到 ...

  2. HDU 4497 GCD and LCM 素因子分解+ gcd 和 lcm

    题意: 给两个数,lll 和 ggg,为x , y , z,的最小公倍数和最大公约数,求出x , y , z 的值有多少种可能性 思路: 将x , y , z进行素因子分解 素因子的幂次 x a1 a ...

  3. 3分钟学会简单使用Vim

    Vim是一款运行在命令行里的文字编辑器,它是Linux人员的标配.在Windows环境下也可以有特别的用处,比如创建没有文件名的文件(.gitignore). Vim的功能十分强大,以至于有一些人对它 ...

  4. mybatis简单项目

    1,mybatis MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可 ...

  5. String是否相等、new的时候创建了几个对象等问题详解

    问题一 这段代码创建了几个对象? String str1 = new String("aa"); 答案是两个 "aa"对象和String对象 Java代码在编译 ...

  6. JS面向对象介绍

    JS面向对象介绍 首先面向对象是什么?为什么要使用面向对象. 因为JavaScript对每个创建的对象都会自动设置一个原型(谷歌火狐中是proto),指向它的原型对象prototype,举个例子: f ...

  7. Activiti工作流框架学习笔记(二)之springboot2.0整合工作流Activiti6.0

    以前在工作当中做过不少与工作流Activiti有关的工作,当时都是spring集成activiti5.22的项目,现在回过头去看,其实版本已经稍微老了,因此,基于先前的工作经验,决定用较新版本的技术来 ...

  8. 手工注入——access手工注入实战和分析

    今天进行了access手工注入,下面是我的实战过程和总结. 实战环境使用的是墨者学院的在线靶场.下面咱们直接进入主题. 第一步,判断注入点 通过‘ 或者 and 1=1 和 and 1=2 是否报错, ...

  9. codeforces 1038a(找最长的前k个字母出现相同次数的字符串)

    codeforces 1038a You are given a string s of length n, which consists only of the first k letters of ...

  10. STL(六)——map、multimap

    STL--map.multimap 文章目录 STL--map.multimap 关联容器与map的介绍 map与set的异同 map与multimap的异同 map类对象的构造 map添加元素 ma ...