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 ...
随机推荐
- 英文短语和单词备忘 - as well as
English phrases and vocabulary notes: as well as "as well as" 是一个连接词组,通常用于连接两个相似的元素,以强调两者都 ...
- 工具 – Prettier、ESLint、Stylelint
前言 以前在 Webpack 学习笔记 有稍微介绍过它们.这篇是单独整理版. 参考 一文彻底读懂ESLint 你的ESLint真的需要Prettier吗? 搞懂eslint和prettier等的关系 ...
- Let's Encrypt Free SSL – Certify The Web
介绍 随着 Let's Encrypt 的普及. 现在为网站升级到 HTTPS 已经不需要付费了. Let's Encrypt 的 SSL 是免费的, 每 3 个月需要更新一次. 可以完全用 API ...
- PyCharm 的一些基本设置&&常用插件&&快捷键
PyCharm一些基本设置 1.主题色彩 2.添加设置:Ctrl+鼠标滚轮上下调节字体大小 3. 中文语言包 4.翻译插件 5.快捷键
- 10-30 NOIP模拟赛
10-30 NOIP模拟赛 今天分数还看的过去,只是第二题没有正解,第三题没有35我表示很伤心.必须继续努力,保持内心纯净,心无杂念,知行合一,摒除恶念. 100 + 80 + 5 = 185 芜湖! ...
- 数据库日常实操优质文章分享(含Oracle、MySQL等) | 11月刊
墨天轮社区正持续举办[聊聊故障处理那些事儿]DBA专题征文活动中,每月进行评优发奖,鼓励大家记录工作中遇到的数据库故障处理过程,不仅用于自我复盘与分析,同时也能帮助其他的同仁们避坑. 这里为大家整理出 ...
- .NET高级调试 - 3.12 sosex实用的几个命令介绍
简介 sosex是sos的一个拓展,主要目的是将一些繁琐的排查过程脚本化,比如探测死锁,设置断点等.更加方便快捷协助我们排查问题. 比较可惜的是,在.net core中不可用,作者已经不更新了. 更多 ...
- 云原生周刊:OpenTofu 宣布正式发布 | 2023.1.15
开源项目推荐 kubeaudit kubeaudit 是一个开源项目,旨在帮助用户对其 Kubernetes 集群进行常见安全控制的审计.该项目提供了工具和检查规则,可以帮助用户发现潜在的安全漏洞和配 ...
- Java 当中使用 “google.zxing ”开源项目 和 “github 的 qrcode-plugin” 开源项目 生成二维码
Java 当中使用 "google.zxing "开源项目 和 "github 的 qrcode-plugin" 开源项目 生成二维码 @ 目录 Java 当中 ...
- HTML 中 script 标签的属性和加载顺序
script 标签默认是阻塞加载的,也就是先下载src内容,然后执行src内容,然后再往后读文档 head 中的 script 按顺序加载执行,然后再加载 body 的元素. 把 script 移动到 ...