XJTUPC2023
J. 大秦酒店欢迎您
题解
我们考虑莫队
首先我们预处理出处于位置\(x\)的颜色下一次出现的位置\(nxt[x]\)以及上一次出现的位置\(pre[x]\)
莫队上维护一下信息:
\(Ans\):\([l,r]\)的所有子区间的颜色数之和
\(num\):\([l,r]\)的颜色数
\(Lans\):\([l,l],[l,l + 1],[l,l + 2]...[l,r]\)这些区间的颜色数之和
\(Rans\):\([r,r],[r - 1, r],[r - 2, r]...[l,r]\)这些区间的颜色数之和
\(cnt[x]\):颜色\(x\)的出现次数
- 我们以左端点\(l\)向左扩张为例, 表示左端点向左扩张对维护的信息的影响
\(l:=l-1\)
\(cnt[col[l]]:=cnt[col[l]] + 1\),颜色出现次数更新的同时更新\(num\)
\(Rans:=Rans + num\)
\(Lans := Lans + min(r, nxt[l]-1) - l + 1\)
\(Ans := Ans + Lans\)
- 那么对于其他操作的影响也是类似的
const int mod = (1ll << 32);
const int N = 5e5 + 10, M = 4e5 + 10;
const int B = sqrt(N) + 1;
int n, q, a[N];
int id[N], Ans, Lans, Rans, num, cnt[N], nxt[N], pre[N], ans[N], pos[N];
struct QUERY
{
int l, r, idx;
bool operator<(const QUERY &t) const
{
if (id[l] == id[t.l])
{
if (id[l] & 1)
return r < t.r;
else
return r > t.r;
}
else
return l < t.l;
}
} qry[N];
void del(int l, int r, int op)
{
if (op == 1) // Left
{
Ans -= Lans;
Lans -= min(r, nxt[l] - 1) - l + 1;
Rans -= num;
cnt[a[l]]--;
if (cnt[a[l]] == 0)
num--;
}
else // Right
{
Ans -= Rans;
Rans -= r - max(l, pre[r] + 1) + 1;
Lans -= num;
cnt[a[r]]--;
if (cnt[a[r]] == 0)
num--;
}
}
void add(int l, int r, int op)
{
if (op == 1) // Left
{
cnt[a[l]]++;
if (cnt[a[l]] == 1)
num++;
Rans += num;
Lans += min(r, nxt[l] - 1) - l + 1;
Ans += Lans;
}
else // Right
{
cnt[a[r]]++;
if (cnt[a[r]] == 1)
num++;
Lans += num;
Rans += r - max(l, pre[r] + 1) + 1;
Ans += Rans;
}
}
void solve()
{
cin >> n >> q;
for (int i = 1; i <= n; ++i)
{
cin >> a[i];
pre[i] = 0;
if (pos[a[i]])
{
pre[i] = pos[a[i]];
nxt[pos[a[i]]] = i;
}
pos[a[i]] = i;
nxt[i] = n + 1;
}
for (int i = 1; i <= q; ++i)
{
cin >> qry[i].l >> qry[i].r;
qry[i].idx = i;
}
for (int i = 1; i <= n; ++i) // 分块
id[i] = (i - 1) / B + 1;
sort(qry + 1, qry + q + 1); // 对查询进行排序
for (int i = 1, l = 1, r = 0; i <= q; ++i)
{
while (l > qry[i].l)
add(--l, r, 1);
while (r < qry[i].r)
add(l, ++r, 2);
while (l < qry[i].l)
del(l++, r, 1);
while (r > qry[i].r)
del(l, r--, 2);
ans[qry[i].idx] = Ans;
}
for (int i = 1; i <= q; ++i)
cout << ans[i] % mod << endl;
}
M. 斑马子树
\(1 \leq n \leq 10^5\)
题解
- 我们考虑如果一颗子树是斑马子树,那么这颗子树能够产生贡献的时间区间段是多少
- 我们考虑\(dp\)出子树\(u\)中最早变成斑马子树的时间戳\(l\),最晚变成非斑马子树的时间戳\(r\)
- 那么\([l,r]\)的时间段上\(u\)的贡献一直为\(1\),我们考虑差分,最后前缀和统计答案即可
// M. 斑马子树
const int N = 2e5 + 10, M = 4e5 + 10;
int n, t[N], mi[N], mx[N], ans[N];
vector<int> g[N];
void dfs(int u, int par)
{
mi[u] = mx[u] = t[u];
for (auto v : g[u])
{
if (v == par)
continue;
dfs(v, u);
mi[u] = min(mi[u], mi[v]);
mx[u] = max(mx[u], mx[v]);
}
ans[mi[u]]++;
ans[mx[u]]--;
}
void solve()
{
cin >> n;
for (int i = 2; i <= n; ++i)
{
int u;
cin >> u;
g[u].push_back(i);
g[i].push_back(u);
}
for (int i = 1; i <= n; ++i)
{
int u;
cin >> u;
t[u] = i;
}
dfs(1, 0);
for (int i = 1; i <= n; ++i)
{
ans[i] = ans[i - 1] + ans[i];
cout << ans[i] << "\n "[i < n];
}
}
随机推荐
- 钉钉H5微应用本地开发调试记录
准备工具: 手机(ios,安卓) 安卓手机可以用网易Mumu模拟器,下载一个移动版钉钉 钉钉开放文档 本地开发的话,可以去钉钉后台管理系统,将你的本地ip地址配置成应用的首页,比如 10.xx.xx. ...
- 鸿蒙(Harmony) NEXT - AlphabetIndexer实现联系人字母索引
鸿蒙(Harmony) NEXT 9月份就要正式上架了,并且不会再兼容安卓平台,于是我也赶紧给App开发鸿蒙版本,接下来会写一系列的Harmony开发教程. 今天使用AlphabetIndexer实现 ...
- RxJS 系列 – Subject
前言 RxJS 两大概念 Observable 和 Subject. 上一篇介绍了 Observable 这篇继续接受 Subject. 参考 RxJS 建立 Observable 的基礎 - Obs ...
- laravel框架中保留条件搜索
前段代码 <form action="admin_index" method="get"> <input type="text&qu ...
- Linux:/proc/meminfo参数详细解释
Linux:/proc/meminfo参数详细解释 一.Linux内存总览图 二.meminfo参数的详细介绍 /proc/meminfo是了解Linux系统内存使用状况的主要接口,我们最常用的&qu ...
- pytorch中y.data.norm()的含义
import torch x = torch.randn(3, requires_grad=True) y = x*2 print(y.data.norm()) print(torch.sqrt(to ...
- CSharp的lambda表达式的使用
using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using Syst ...
- 小程序的三大API
小程序的API有宿主环境提供的 : ps:浏览器的定义对象是 window 而微信中的顶级对象是wx :都是不用声明就能调用 : 1. 事件监听 以on开头,监听事件的触发 eg:onWindowRe ...
- webpack配置 alias用于方便引用文件
.markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rg ...
- 防火墙NAT配置与DHCP下发
该实验如果有做的不足的地方请见谅 实验目标: 按要求划分区域,公司内部办公区为trust,服务器区为dmz,外部网络为untrust. PC1和PC2为公司内部办公区,需要从防火墙中的DHCP服务获取 ...


