2018-2019 9th BSUIR Open Programming Championship
I. Equal Mod Segments
\(1 \leq n \leq 1e5\)
\(1 \leq a_i \leq 3e5\)
题解:ST表 + 扫描线 + 二维偏序
取模存在一个不错的性质:\(x \%p\)要么\(x\)不变,要么\(x\)至少整除\(2\)
所以我们考虑固定左端点\(l\),存在\(log\ a_l\)段区间,使得右端点\(r\)在每段区间\([p,q]\)内\(a_l\ mod\ a_{l + 1}...mod\ a_r,r\in[p,q]\)不变
我们可以通过\(ST\)表+二分来预处理所有固定左端点和固定右端点的区间,并将所有模数相同的区间放入同一个\(vector\)中,预处理复杂度 \(O(nlog^2n)\)
那么我们考虑区间\([l,r]\)满足什么条件,才能对答案产生贡献
我们设对于\(l\)来说,模数为\(p\)的右端点\(r\)所在区间为\([L_1,R_1]\),对于\(r\)来说,模数为\(p\)的左端点\(l\)所在区间为\([L_2,R_2]\),那么只要保证\(L_1\leq r \leq R_1 \and L_2\leq l \leq R_2\),那么区间\([l,r]\)就能对答案产生贡献
我们把条件抽象到二维平面上,横坐标为\(l\),纵坐标为\(r\),可以得到:
- 所以我们只要对每个模数的\(vector\)跑一次扫描线即可,扫描\(x\)轴,线段树维护\(y\)轴,求交点数量即可
const int N = 3e5 + 10, M = 4e5 + 10;
int n, a[N], st[N][18], lg2[N];
vector<array<int, 4>> vec[N];
struct info
{
int sum;
friend info operator+(const info &a, const info &b)
{
info c;
c.sum = a.sum + b.sum;
return c;
}
};
struct SEG
{
info val;
} seg[N << 2];
void up(int id)
{
seg[id].val = seg[lson].val + seg[rson].val;
}
void change(int id, int l, int r, int x, int val)
{
if (l == r)
{
seg[id].val.sum += val;
return;
}
int mid = l + r >> 1;
if (x <= mid)
change(lson, l, mid, x, val);
else
change(rson, mid + 1, r, x, val);
up(id);
}
info query(int id, int l, int r, int ql, int qr)
{
if (ql <= l && r <= qr)
return seg[id].val;
int mid = l + r >> 1;
if (qr <= mid)
return query(lson, l, mid, ql, qr);
else if (ql > mid)
return query(rson, mid + 1, r, ql, qr);
else
return query(lson, l, mid, ql, qr) + query(rson, mid + 1, r, ql, qr);
}
void build()
{
for (int i = 1; i <= n; ++i)
st[i][0] = a[i];
for (int i = 2; i <= n; ++i)
lg2[i] = lg2[i >> 1] + 1;
for (int j = 1; j <= 15; ++j)
for (int i = 1; i + (1ll << j) - 1 <= n; ++i)
st[i][j] = min(st[i][j - 1], st[i + (1ll << (j - 1))][j - 1]);
}
int query(int l, int r)
{
if (l > r)
return INF;
int len = lg2[r - l + 1];
return min(st[l][len], st[r - (1ll << len) + 1][len]);
}
void solve()
{
cin >> n;
int m = 0;
for (int i = 1; i <= n; ++i)
{
cin >> a[i];
m = max(m, a[i]);
}
build();
for (int i = 1; i <= n; ++i)
{
int now = a[i];
for (int j = i, l, r; j <= n; j = r + 1)
{
l = j, r = n;
while (l <= r)
{
int mid = l + r >> 1;
if (query(j + 1, mid) > now)
l = mid + 1;
else
r = mid - 1;
}
vec[now].push_back({0, i, j, r});
if (r + 1 <= n)
now %= a[r + 1];
}
}
for (int i = n; i >= 1; --i)
{
int now = a[i];
for (int j = i, l, r; j >= 1; j = l - 1)
{
l = 1, r = j;
while (l <= r)
{
int mid = l + r >> 1;
if (query(mid, j - 1) > now)
r = mid - 1;
else
l = mid + 1;
}
vec[now].push_back({1, i, l, j});
if (l - 1 >= 1)
now %= a[l - 1];
}
}
int ans = 0;
for (int i = 0; i <= m; ++i)
{
if (vec[i].empty())
continue;
vector<array<int, 4>> evt;
for (auto [op, k, l, r] : vec[i])
{
if (op == 0) // 查询
evt.push_back({k, 0, l, r});
else
{
evt.push_back({l, -1, k, 1}); // 添加贡献
evt.push_back({r, 1, k, -1}); // 删除贡献
}
}
// 扫描线
sort(all(evt));
for (auto [y, op, l, r] : evt)
{
if (op == 0)
ans += query(1, 1, n, l, r).sum;
else
change(1, 1, n, l, r);
}
}
cout << ans << endl;
}
K. Innovations
题解:树链剖分 + 势能线段树
- 考虑到根号的性质,所以显然势能线段树维护\(dfs\)序
- 我们考虑每条边对答案产生的贡献为\(sz[v] \times (n - sz[v]),sz[v]为v的子树大小\)
- 设边权为\(w[v]\),每条边的贡献为\(p[v]\),那么每条边对答案的贡献为\(w[v] \times p[v]\),所以我们线段树直接维护答案,如果该区间不全为\(1\)就暴力递归到叶子节点进行修改
const int N = 2e5 + 10;
const int mod = 1e9 + 7;
int n, m, sz[N], p[N], dep[N], top[N], hson[N], l[N], r[N], fa[N], w[N], idx, mp[N];
vector<pair<int, int>> g[N];
void dfs1(int u, int par)
{
fa[u] = par;
dep[u] = dep[par] + 1;
sz[u] = 1;
hson[u] = -1;
for (auto [v, val] : g[u])
{
if (v == par)
continue;
dfs1(v, u);
sz[u] += sz[v];
w[v] = val;
p[v] = sz[v] * (n - sz[v]);
if (hson[u] == -1 || sz[v] > sz[hson[u]])
hson[u] = v;
}
}
void dfs2(int u, int head)
{
top[u] = head;
l[u] = ++idx;
mp[idx] = u;
if (hson[u] != -1)
dfs2(hson[u], head);
for (auto [v, val] : g[u])
{
if (v == fa[u])
continue;
if (v == hson[u])
continue;
dfs2(v, v);
}
r[u] = idx;
}
struct info
{
int sum, flag; // flag 代表区间是否全为 1
friend info operator+(const info &a, const info &b)
{
info c;
c.sum = (a.sum + b.sum) % mod;
c.flag = a.flag && b.flag;
return c;
}
info(int sum = 0, int flag = 0) : sum(sum), flag(flag) {}
};
struct SEG
{
int lazy;
info val;
} seg[N << 2];
void up(int id)
{
seg[id].val = seg[lson].val + seg[rson].val;
}
void build(int id, int l, int r)
{
if (l == r)
{
if (mp[l] == 1)
{
seg[id].val = info(0, 1);
return;
}
if (w[mp[l]] == 1)
seg[id].val = info(w[mp[l]] * p[mp[l]], 1);
else
seg[id].val = info(w[mp[l]] * p[mp[l]], 0);
return;
}
int mid = l + r >> 1;
build(lson, l, mid);
build(rson, mid + 1, r);
up(id);
}
void modify(int id, int l, int r, int ql, int qr)
{
if (ql <= l && r <= qr && seg[id].val.flag)
return;
if (l == r)
{
w[mp[l]] = (int)(sqrt(w[mp[l]]));
if (w[mp[l]] == 1)
seg[id].val.flag = 1;
else
seg[id].val.flag = 0;
seg[id].val.sum = w[mp[l]] * p[mp[l]];
return;
}
int mid = l + r >> 1;
if (qr <= mid)
modify(lson, l, mid, ql, qr);
else if (ql > mid)
modify(rson, mid + 1, r, ql, qr);
else
{
modify(lson, l, mid, ql, qr);
modify(rson, mid + 1, r, ql, qr);
}
up(id);
}
void solve()
{
cin >> n >> m;
for (int i = 1; i < n; ++i)
{
int u, v, w;
cin >> u >> v >> w;
g[u].push_back({v, w});
g[v].push_back({u, w});
}
dfs1(1, 0);
dfs2(1, 1);
build(1, 1, n);
cout << seg[1].val.sum << endl;
while (m--)
{
int u, v;
cin >> u >> v;
while (top[u] != top[v])
{
if (dep[top[u]] > dep[top[v]])
{
modify(1, 1, n, l[top[u]], l[u]);
u = fa[top[u]];
}
else
{
modify(1, 1, n, l[top[v]], l[v]);
v = fa[top[v]];
}
}
if (dep[u] > dep[v] && l[v] + 1 <= l[u])
modify(1, 1, n, l[v] + 1, l[u]);
else if (dep[u] < dep[v] && l[u] + 1 <= l[v])
modify(1, 1, n, l[u] + 1, l[v]);
cout << seg[1].val.sum << endl;
}
}
2018-2019 9th BSUIR Open Programming Championship的更多相关文章
- 2019-2020 10th BSUIR Open Programming Championship. Semifinal
2019-2020 10th BSUIR Open Programming Championship. Semifinal GYM链接https://codeforces.com/gym/103637 ...
- 20172328 2018—2019《Java软件结构与数据结构》第二周学习总结
20172328 2018-2019<Java软件结构与数据结构>第二周学习总结 概述 Generalization 本周学习了第三章集合概述--栈和第四章链式结构--栈.主要讨论了集合以 ...
- COCI 2018/2019 CONTEST #2 T4 Maja T5Sunčanje Solution
COCI 2018/2019 CONTEST #2 T4 T5 Solution abstract 花式暴力 #2 T5 Sunčanje 题意 按顺序给你1e5个长方形(左下角坐标&& ...
- The 2018 ACM-ICPC China JiangSu Provincial Programming Contest快速幂取模及求逆元
题目来源 The 2018 ACM-ICPC China JiangSu Provincial Programming Contest 35.4% 1000ms 65536K Persona5 Per ...
- Ural Sport Programming Championship 2015
Ural Sport Programming Championship 2015 A - The First Day at School 题目描述:给出课程安排,打印一个课程表. solution 暴 ...
- The 2018 ACM-ICPC China JiangSu Provincial Programming Contest J. Set
Let's consider some math problems. JSZKC has a set A=A={1,2,...,N}. He defines a subset of A as 'Meo ...
- The 2018 ACM-ICPC China JiangSu Provincial Programming Contest I. T-shirt
JSZKC is going to spend his vacation! His vacation has N days. Each day, he can choose a T-shirt to ...
- 工具软件集合 Adobe AE PS Pr CC 2018 2019 破解教程
来源https://mp.weixin.qq.com/s/zeq1sTmaPsKt7Bsok0Ldrg(若链接失效,请关注软件安装管家公众号) 相关链接 Office 2019破解教程 Adobe 2 ...
- 2018 – 2019 年前端 JavaScript 面试题
JavaScript 基础问题 1.使以下代码正常运行: JavaScript 代码: const a = [1, 2, 3, 4, 5]; // Implement this a.multiply( ...
- March 03rd, 2018 Week 9th Saturday
No cross, no crown. 不经历风雨,怎能见彩虹. Sometimes you can see a beautiful rainbow high in the sky without h ...
随机推荐
- GRLSTM: 基于图的残差LSTM轨迹相似性计算《GRLSTM: Trajectory Similarity Computation with Graph-Based Residual LSTM》(轨迹路网融合、知识图谱嵌入、图神经网络、残差网络、点融合图、多头图注意力网络GAT、残差LSTM、点感知损失函数(图的点损失函数、轨迹的点损失函数))
2023年10月18日,14:14. 来不及了,这一篇还是看的翻译. 论文:GRLSTM: Trajectory Similarity Computation with Graph-Based Res ...
- CSS & JS Effect – Dialog Modal
效果 参考: Youtube – Create a Simple Popup Modal Youtube – Create a Modal (Popup) with HTML/CSS and Java ...
- SQL server temporal table 学习笔记
refer: https://blog.csdn.net/Hehuyi_In/article/details/89670462 https://docs.microsoft.com/en-us/sql ...
- ASP.NET Core C# 反射 & 表达式树 (第二篇)
前言 上一篇讲到了各种反射的操作方式, 这一篇主要说说如何找到类型. Type Information 在找类型的时候, 除了依据简单的 string 以外, 还会用到很多类型属性来做判断. 比如它是 ...
- 一组.NET MAUI绘制的开源控件 - AlohaKit
前言 今天大姚给大家分享一组.NET MAUI绘制的开源.免费(MIT License)UI控件库:AlohaKit. MAUI介绍 .NET MAUI是一个开源.免费(MIT License)的跨平 ...
- 暑假集训PVZ提高模拟9
没关 exe 让这货挂了一天 UPD:又挂了一晚上,现在被我正义制裁了 A.大众点评 交互红题啊,交互会写,但是忘记判 \(n=1\) 了 这个题交互库函数实现起来还是挺简单的,我 Windows 不 ...
- 深入理解 Nuxt.js 中的 app:created 钩子
title: 深入理解 Nuxt 中的 app created 钩子 date: 2024/9/26 updated: 2024/9/26 author: cmdragon excerpt: 摘要:本 ...
- Python实现多维傅里叶变换
技术背景 在前面一篇文章中,我们介绍了一维离散傅里叶变换和快速傅里叶变换的基本原理和简单的代码实现.本文补充一个多维傅里叶变换的场景,以及简单的Python实现. 二维傅里叶变换 首先回顾一下上一篇文 ...
- WebGL学习笔记
完整 demo 和 lib 文件可以在 https://github.com/tengge1/webgl-guide-code 中找到. 第 2 章 WebGL 入门 第一个 WebGL 程序 fun ...
- 国产OS 中标麒麟下 C# 桌面应用开发环境搭建笔记
1.中标麒麟 7.0 x86 桌面版 默认安装创建用户时,如果没勾选 root 用户使用相同的口令,那么安装完成以后,root 是没有设置口令的,通过 sudo passwd root 输入当前普通用 ...


