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. 27 首页banner文库失效

    安卓app 首页banner文库没有连接功能

  2. php页面调用微信扫一扫

    function.php <?php define("appID", "微信公众号appId"); define("appsecret" ...

  3. MViTv2:Facebook出品,进一步优化的多尺度ViT | CVPR 2022

    论文将Multiscale Vision Transformers (MViTv2) 作为图像和视频分类以及对象检测的统一架构进行研究,结合分解的相对位置编码和残差池化连接提出了MViT的改进版本 来 ...

  4. 洛谷P10693

    洛谷P10693 好奇怪的题目编号 思路提取 input 11 2 13 4 5 3 7 9 9 11 11 12 output 9 以人造数据为例. 首先我们让\(i\)\(\to\)\(a_i\) ...

  5. 青少年CTF擂台挑战赛 2024 #Round 1

    青少年CTF擂台挑战赛 2024 #Round 1 crypto 1.解个方程 题目: 欢迎来到青少年CTF,领取你的题目,进行解答吧!这是一道数学题!! p = 474356125652182661 ...

  6. 【Mybatis】Bonus01 笔记资料

    对原生JDBC程序的问题总结 public void jdbc() { // 声明Connection对象 Connection con; // 驱动程序名 String driver = " ...

  7. 【Vue】15 VueX

    [什么是VueX?] VueX是一个专门为Vue.js应用程序开发的状态管理模式, 采用集中式存储管理应用的所有组件状态, 以相应的规则保证按照一种可预测的方式发生改变. 即把多个组件的变量统一放到一 ...

  8. 【转载】 Sun RPC 编程简介

    原文地址: http://blog.chinaunix.net/uid-1724205-id-2813082.html ======================================== ...

  9. 几乎纯css实现弹出框

    今天需要做一个弹出框,右下角提示的那种 ,看了一两个jquery的插件 总是不太满意 .一方面js内容太多,另一方面 不太好配合已经存在的样式使用.所以 就自己用css直接实现了下 效果还可以 . 上 ...

  10. 最佳实践:解读GaussDB(DWS) 统计信息自动收集方案

    摘要:现在商用优化器大多都是基于统计信息进行查询代价评估,因此统计信息是否实时且准确对查询影响很大,特别是分布式数据库场景.本文详细介绍GaussDB(DWS)如何实现了一种轻量.实时.准确的统计信息 ...