T1 游戏

标签

尺取 线段树 单调队列

线段树进阶

思路

抽象题意,相当于有 \(t\) 个点,有 \(n\) 个下接 \(x\) 轴的矩形。

首先明显可以按照 \(c\) 排序,然后尺取。

写法

线段树记录每区间内未被覆盖的最大高度。

因为插入和删除的顺序相对不变,一个单调队列维护该区间内矩形高度即可,若有删除操作则向儿子取 \(\max\) 重新计算 \(mx\)

代码

常数极大,可使用内存池优化。

code
ci N = 1e6 + 9;
ci inf = 2e9; int t, n, ans(inf);
int a[N], b[N], c[N], v[N], h[N], id[N]; bool cmp(int x, int y) {return c[x] < c[y];} struct SGT {
#define lc ((u) << 1)
#define rc ((u) << 1 | 1)
int mx[N << 2], buf[N * 40];
unsigned int head[N << 2], tail[N << 2];
il void pushup_mx(int u) {
if(head[u] > tail[u]) return;
if(v[q[u][head[u]]] >= mx[u]) mx[u] = 0;
}
il void pushup(int u) {
mx[u] = max(mx[lc], mx[rc]);
pushup_mx(u);
}
il void build(int u, int l, int r) {
if(l == r) return mx[u] = h[l], void();
int mid = (l + r) >> 1;
build(lc, l, mid);
build(rc, mid + 1, r);
pushup(u);
}
il void insert(int u, int l, int r, int a, int b, int i) {
if(a <= l && r <= b) {
while(head[u] < q[u].size() && v[*(-- q[u].end())] <= v[i]) q[u].pop_back();
q[u].eb(i);
if(v[q[u][head[u]]] >= mx[u]) mx[u] = 0;
return;
}
if(b < l || r < a) return;
int mid = (l + r) >> 1;
insert(lc, l, mid, a, b, i);
insert(rc, mid + 1, r, a, b, i);
pushup(u);
}
il void erase(int u, int l, int r, int a, int b, int i) {
if(a <= l && r <= b) {
if(q[u][head[u]] == i) {
++ head[u];
if(l == r) {
mx[u] = h[l];
pushup_mx(u);
}
else {
pushup(u);
}
}
return;
}
if(b < l || r < a) return;
int mid = (l + r) >> 1;
erase(lc, l, mid, a, b, i);
erase(rc, mid + 1, r, a, b, i);
pushup(u);
}
} tree; il void ins(int i) {
tree.insert(1, 1, t, a[i], b[i], i);
} il void ers(int i) {
tree.erase(1, 1, t, a[i], b[i], i);
} int main() {
freopen("game.in", "r", stdin);
freopen("game.out", "w", stdout);
rd(t); rd(n);
rep(i, 1, n) {
rd(a[i], b[i], c[i], v[i]);
id[i] = i;
}
sort(id + 1, id + n + 1, cmp);
rep(i, 1, t) rd(h[i]);
tree.build(1, 1, t);
int L = 1;
rep(_i, 1, n) {
int i = id[_i];
ins(i);
while(tree.mx[1] == 0) {
cmin(ans, c[i] - c[id[L]]);
ers(id[L]); ++ L;
}
}
pt("%d\n", ans);
return 0;
}

T2 驻军

标签

长链剖分,树上前缀和进阶

思路

订正的时候没有对答案取模再乘,dfs 时没有判长链。

考虑将找链转化为对端点处理,发现可以通过处理将答案变为只与 \(lca(x, y), x, y\) 有关的形式,这样才能进行长链剖分。

约定

\(f_u\) 表示 \(u\) 子树所有点到 \(u\) 的距离和。

\(e_{u, v}\) 表示 \((u\to v)\) 的边权。

\(h_u\) 表示 \(u\) 子树所有点到 \(u\) 的距离和。

\(sz_u\) 表示 \(u\) 子树的大小。

\(w_v\) 表示 \((fa_v\to v)\) 的贡献,等于 \(sz_v\cdot e_{fa_v, v}\)。

\(s_u\) 表示从 \(u\) 到根(可设为 \(1\))的简单路径上的边的 \(w\) 之和,等于 \(w_u + w_{fa_u} + \cdots\)

转移

若路径为 \(x, y\),设 \(lca(x, y) = u\) 则答案为 \(h_u + f_u - (s_x - s_u) - (s_y - s_u)\)。

这个比较难,可对每条边快速统计多算的贡献,减去即可。

\(f_u = \sum\limits_{u\to v} (f_v + w_v)\)

\(s_v = s_u + w_v\)

\(h_v = (n - sz_v)\cdot e_{u, v} + h_u + f_u - f_v - w_v\)

代码

code
ci N = 2e6 + 9;
const ll INF = 1e18; int n, k; ll sz[N], f[N], s[N], h[N], w[N]; vector<pii> A[N]; void dfs1(int u, int la) {
sz[u] = 1;
for(pii e : A[u]) {
int v = e.fi;
if(v == la) continue;
dfs1(v, u);
sz[u] += sz[v];
w[v] = sz[v] * e.se;
f[u] += f[v] + w[v];
}
} int depth[N], son[N];
void dfs2(int u, int la) {
depth[u] = 1;
for(pii e : A[u]) {
int v = e.fi;
if(v == la) continue;
s[v] = s[u] + w[v];
h[v] = 1LL * (n - sz[v]) * e.se + h[u] + (f[u] - f[v] - w[v]);
dfs2(v, u);
cmax(depth[u], depth[v] + 1);
if(depth[v] + 1 == depth[u]) son[u] = v;
}
} ll buc[N], *mx[N], ans(INF); void dfs(int u, int la) {
mx[u][1] = s[u];
if(son[u]) {
mx[son[u]] = mx[u] + 1;
dfs(son[u], u);
for(pii e : A[u]) {
int v = e.fi;
if(v == la || v == son[u]) continue;
mx[v] = mx[u] + depth[u];
dfs(v, u);
rep(i, 1, depth[v]) {
if(i > 0 && k - i > 1 && i <= depth[v] && k - i <= depth[u]) {
cmin(ans, h[u] + f[u] + 2 * s[u] - mx[u][k - i] - mx[v][i]);
if(ans < 0) {
printf("%lld %lld %lld\n", h[u], f[u], s[u]);
printf("u-road = %d v = %d\n", u, v), exit(0);
}
}
}
rep(i, 1, depth[v]) cmax(mx[u][i + 1], mx[v][i]), mx[v][i] = 0;
}
}
if(depth[u] >= k) {
cmin(ans, h[u] + f[u] + s[u] - mx[u][k]);
if(ans < 0) printf("u-list = %d\n", u),exit(0);
}
} ci mod = 998244353; ll fpow(ll a, ll x) {
ll res = 1;
while(x) {
if(x & 1) res = res * a % mod;
a = a * a % mod;
x >>= 1;
}
return res;
} int dis[N];
void _dfs(int u, int la) {
dis[u] = dis[la] + 1;
for(pii e : A[u]) {
if(e.fi == la) continue;
_dfs(e.fi, u);
}
} int main() {
// freopen("barrack.in", "r", stdin);
// freopen("barrack.out", "w", stdout);
freopen("a.in", "r", stdin);
rd(n, k);
rep(i, 2, n) {
int x, y, z;
rd(x, y, z);
A[x].eb(mp(y, z));
A[y].eb(mp(x, z));
} int st = 1;
_dfs(1, 0);
rep(i, 2, n) {
if(dis[i] > dis[st]) {
st = i;
}
}
_dfs(st, 0);
rep(i, 1, n) {
if(dis[i] > dis[st]) {
st = i;
}
}
if(dis[st] < k) return puts("-1"), 0; dfs1(1, 0);
dfs2(1, 0);
mx[1] = buc;
dfs(1, 0);
printf("%lld\n", ans % mod * fpow(n, mod - 2) % mod);
return 0;
}

T3 序列

标签

离线

线段树入门

思路

首先有 \(\gcd(x, x - v) = \gcd(x, x + v) = \gcd(x, v)\)

考虑将所有操作离线,对于每一个位置 \(i\) 处理询问

第 \(j\) 次询问 \(p,k\) 相当于将 \(0\sim k - 1\) 的前缀和\(= a_i + \sum\limits_{q < k, i\in [l_q, r_q]} v_q\) 与 \(k\sim j\) 的 \(v\) 的 \(\gcd\) 求一个 \(\gcd\),开个线段树维护一下区间和和区间 \(\gcd\) 即可。

感觉比 T2 简单。

代码

代码好写。

code
ci N = 2.5e5 + 9;

int n, q;
int a0[N], qval[N], op[N];
ll ans[N];
vector<int> ins[N], ers[N];
vector<int> qry[N]; ll gcd(ll a, ll b) {return !b ? a : gcd(b, a % b);} struct SGT {
#define lc ((u) << 1)
#define rc ((u) << 1 | 1)
int tr_gcd[N << 2];
ll tr_sum[N << 2];
void push_up(int u) {
tr_sum[u] = tr_sum[lc] + tr_sum[rc];
tr_gcd[u] = gcd(tr_gcd[lc], tr_gcd[rc]);
}
void modify(int u, int l, int r, int loc, int var) {
if(l == r) {
tr_gcd[u] = tr_sum[u] = var;
return;
}
int mid = (l + r) >> 1;
if(loc <= mid) modify(lc, l, mid, loc, var);
else modify(rc, mid + 1, r, loc, var);
push_up(u);
}
ll querysum(int u, int l, int r, int a, int b) {
if(a <= l && r <= b) return tr_sum[u];
if(b < l || r < a) return 0;
int mid = (l + r) >> 1;
return querysum(lc, l, mid, a, b) + querysum(rc, mid + 1, r, a, b);
}
int querygcd(int u, int l, int r, int a, int b) {
if(a <= l && r <= b) return tr_gcd[u];
if(b < l || r < a) return 0;
int mid = (l + r) >> 1;
return gcd(querygcd(lc, l, mid, a, b), querygcd(rc, mid + 1, r, a, b));
}
} tree; int main() {
freopen("sequence.in", "r", stdin);
freopen("sequence.out", "w", stdout);
rd(n, q);
rep(i, 1, n) rd(a0[i]);
rep(i, 1, q) {
rd(op[i]);
if(op[i] == 1) {
int l, r; rd(l, r, qval[i]);
ins[l].eb(i);
ers[r + 1].eb(i);
}
else {
int p; rd(p, qval[i]);
qry[p].eb(i);
}
}
rep(i, 1, n) {
for(int j : ins[i]) {
tree.modify(1, 1, q, j, qval[j]);
}
for(int j : ers[i]) {
tree.modify(1, 1, q, j, 0);
}
for(int j : qry[i]) {
ans[j] = gcd(a0[i] + tree.querysum(1, 1, q, 1, qval[j] - 1), tree.querygcd(1, 1, q, qval[j], j));
}
}
rep(i, 1, q) {
if(op[i] == 2) {
printf("%lld\n", abs(ans[i]));
}
}
return 0;
}

2023/11/15 NOIP 模拟赛的更多相关文章

  1. 11/1 NOIP 模拟赛

    11.1 NOIP 模拟赛 期望得分:50:实际得分:50: 思路:暴力枚举 + 快速幂 #include <algorithm> #include <cstring> #in ...

  2. 11.7 NOIP模拟赛

    目录 2018.11.7 NOIP模拟 A 序列sequence(two pointers) B 锁lock(思路) C 正方形square(埃氏筛) 考试代码 B C 2018.11.7 NOIP模 ...

  3. 【2019.7.15 NOIP模拟赛 T2】与非树(nand)(树形DP)

    树形\(DP\) 实际上,这道题应该不是很难. 我们设\(f_{x,i,j}\)表示在以\(x\)为根的子树内,原本应输出\(i\),结果输出了\(j\)的情况数. 转移时,为了方便,我们先考虑与,再 ...

  4. 【2019.7.15 NOIP模拟赛 T1】夹缝(mirror)(思维题)

    思维题 此题应该是比较偏思维的. 假设一次反射后前进的距离是\(2^x(2y+1)\),则显然,它可以看做是前进距离为\(2^x\)的光线经过了\((2y+1)\)次反射,两者是等价的,甚至后者可能还 ...

  5. 2022.11.15 NOIP2022 模拟赛十

    炸弹威力 Source:洛谷 P6036. 记 \(f_{i,0/1}\) 表示第 \(i\) 个位置为 \(0/1\) 的答案个数,有 DP 转移: \[\begin{aligned} (1-p_i ...

  6. NOIP模拟赛-2018.11.7

    NOIP模拟赛 如果用命令行编译程序可以发现没加头文件之类的错误. 如果用命令行编译程序可以发现没加头文件之类的错误. 如果用命令行编译程序可以发现没加头文件之类的错误. 编译之前另存一份,听说如果敲 ...

  7. NOIP模拟赛-2018.11.6

    NOIP模拟赛 今天想着反正高一高二都要考试,那么干脆跟着高二考吧,因为高二的比赛更有技术含量(我自己带的键盘放在这里). 今天考了一套英文题?发现阅读理解还是有一些困难的. T1:有$n$个点,$m ...

  8. NOIP模拟赛-2018.11.5

    NOIP模拟赛 好像最近每天都会有模拟赛了.今天从高二逃考试跑到高一机房,然而高一也要考试,这回好像没有拒绝的理由了. 今天的模拟赛好像很有技术含量的感觉. T1:xgy断句. 好诡异的题目,首先给出 ...

  9. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  10. NOIP模拟赛 by hzwer

    2015年10月04日NOIP模拟赛 by hzwer    (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...

随机推荐

  1. Mac部署Tomcat8.5

    官网下载 点我直达 启动 将Tomcat包解压后并放到这个目录下:/Users/chenyanbin/plus/tomcat8.5/bin 切换目录: cd /Users/chenyanbin/plu ...

  2. UE4 蓝图查找Actor和Actor标签

    在用UE4 开发数字孪生应用的过程中,有很多业务会涉及到actor的查找,和actor标签的使用. 比如下面的场景中,找出所有的物联网设备进行标注. 通过类查找actor 通过类查找actor,可以查 ...

  3. Python 结合opencv实现图片截取和拼接

    实践环境 python 3.6.2 scikit-build-0.16.7 win10 opencv_python-4.5.4.60-cp36-cp36m-win_amd64.whl 下载地址: ht ...

  4. UE5打包后,无法切换关卡的问题

    首先是普通的会遇到的问题,比如多个Level不在同一目录,或者不在默认的Maps目录打包不成功这时候要设置,Project Settings-> Packaging 上面保证没问题之后,打包发现 ...

  5. 使用 Doxygen 来生成 Box2d 的 API 文档

    对于 Doxygen 以前只听别人说过,而现在使用它也是一个偶然,缘分吧.前两天看 box2d 的官方 sdk 中,发现他有用户手册却没有说明,只是留下了一个 Doxygen 的文件.事情告一段落,然 ...

  6. WordPress基础之基本SEO设置

    基础内容,不会涉及过深,在谷歌SEO教程中会做详细的介绍,我这里只简单讲下. 1. SEO介绍 SEO,又名搜索引擎优化(Search Engine Optimization,缩写为SEO)是透过了解 ...

  7. perf 性能分析工具

    perf 性能分析工具 perf topperf recordperf reportperf listperf stat perf top -p <pid> 例如查看redis进程的内核调 ...

  8. 使用Cython调用CUDA Kernel函数

    技术背景 前面写过一篇关于Cython和C语言混合编程的文章,在Cython中可以使用非常Pythonic的方法去调用C语言中的函数.另外我们也曾在文章中介绍过Python中使用CUDA计算的一种方案 ...

  9. 【Java】轻量Excel读写框架JXL学习

    参考黑马教程: https://www.bilibili.com/video/BV1eA41157va?p=5 写着写着发现有更好的Demo案例: https://cloud.tencent.com/ ...

  10. 【SpringBoot】15 数据访问P3 整合Mybatis

    重新建立一个SpringBoot工程 选择依赖组件 然后删除不需要的Maven&Git文件 还是先查看我们的POM文件 整合Mybatis的组件多了这一个,默认的版本是3.5.4 然后再看看整 ...