P5397 [Ynoi2018] 天降之物 题解
蒟蒻做的第一道黑色的
题意#
第四分块。
你需要实现
- 把序列中所有值为
的数的值变成 。 - 找出一个位置
满足 ,找出一个位置 满足 ,使得 最小,并输出 。
思路#
考虑如何写一个暴力。
用一个
我们发现,这个东西可以用根号分治进行优化。
我们对每一个数的出现次数进行根号分治。
大体思路是对于出现次数大于阀值的预处理答案,查询时直接查。
对于出现次数小于阀值的直接暴力归并。
修改
首先有一个小的
考虑让
- 若两个都大于阀值。
我们直接
- 若一个大于阀值,一个小于阀值。
我们考虑对每一个大于阀值的维护一个附加集合。
我们将小于阀值的加入到附加集合中,在这里,再次考虑根号分治。
如果附加集合的大小小于阀值,那么,此部分复杂度为
如果附加集合的大小大于阀值,我们就全部暴力
所以,此部分复杂度为
- 若两个都小于阀值
我们将两个集合合并,在这里,如第二点一样考虑根号分治。
如果集合的大小小于阀值,那么,此部分复杂度为
如果集合的大小大于阀值,我们就全部暴力
所以,此部分复杂度为
查询
查询比上面的修改有简单多了,毕竟答案什么都预处理完了。
- 若两个都大于阀值。
则查询预处理的答案,并且将两个附加集合进行归并计算,时间复杂度
- 若一个大于阀值,一个小于阀值。
同样查询预处理的答案,并且将附加集合和集合进行归并计算,时间复杂度
- 若两个都小于阀值
直接归并计算即可,时间复杂度
由于
代码实测阀值取
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
const int base = 320;
int n , m , top , len , lastans , a[N] , stk[N] , siz[N] , rel[N] , sum[base][N];
vector<int> f[N];
inline int read()
{
int asd = 0 , qwe = 1; char zxc;
while(!isdigit(zxc = getchar())) if(zxc == '-') qwe = -1;
while(isdigit(zxc)) asd = asd * 10 + zxc - '0' , zxc = getchar();
return asd * qwe;
}
inline void cl(vector<int> &now)
{
vector<int> ne;
now.swap(ne);
}
inline int calc(vector<int> x , vector<int> y)
{
int len1 = x.size() , len2 = y.size() , ans = 100010;
for(int i = 0 , j = 0;i < len1;i++)
{
if(j < len2) ans = min(ans , abs(y[j] - x[i]));
while(j < len2 && y[j] < x[i]) ans = min(ans , x[i] - y[j++]);
if(j < len2) ans = min(ans , abs(y[j] - x[i]));
}
return ans;
}
inline void solve(vector<int> &x , vector<int> &y)
{
vector<int> ne;
int i , j , len1 = x.size() , len2 = y.size() , ans = 100010;
for(i = 0 , j = 0;i < len1;i++)
{
while(j < len2 && y[j] < x[i]) ne.push_back(y[j++]);
ne.push_back(x[i]);
}
while(j < len2) ne.push_back(y[j++]);
y = ne , cl(x);
}
inline void update(int r , int id = 0)
{
stk[r] = stk[r] ? stk[r] : ++top; int x = stk[r];
memset(sum[x] , 0x3f , sizeof sum[x]);
for(int i = 1 , j = N;i <= n;i++)
if(a[i] == r) j = 0; else sum[x][a[i]] = min(sum[x][a[i]] , ++j);
for(int i = n , j = N;i >= 1;i--)
if(a[i] == r) j = 0; else sum[x][a[i]] = min(sum[x][a[i]] , ++j);
cl(f[r]);
}
int main()
{
n = read() , m = read() , memset(sum , 0x3f , sizeof sum) , len = 500;
for(int i = 1;i <= n;i++) a[i] = read() , rel[i] = i;
for(int i = 1;i <= n;i++) f[a[i]].push_back(i) , siz[a[i]]++;
for(int i = 1;i <= n;i++) if(f[i].size() > len) update(i);
for(int i = 1;i <= m;i++)
{
int opt = read() , x = read() ^ lastans , y = read() ^ lastans;
if(opt == 1)
{
int l = rel[x] , r = rel[y];
if(siz[l] == 0 || l == r) continue;
if(siz[l] > siz[r]) rel[y] = l , swap(l , r) , rel[x] = n + 1;
else rel[x] = n + 1; if(l > n || r > n) continue;
if(siz[r] <= len)
{
if(siz[l] + siz[r] <= len)
{
for(int j : f[l]) a[j] = r;
for(int j = 1;j <= top;j++) sum[j][r] = min(sum[j][r] , sum[j][l]);
solve(f[l] , f[r]);
}
else
{
for(int i = 1;i <= n;i++) if(a[i] == l) a[i] = r;
update(r);
}
}
else if(siz[l] <= len)
{
if(siz[l] + f[r].size() <= len)
{
for(int j : f[l]) a[j] = r;
for(int j = 1;j <= top;j++) sum[j][r] = min(sum[j][r] , sum[j][l]);
solve(f[l] , f[r]);
}
else
{
for(int i = 1;i <= n;i++) if(a[i] == l) a[i] = r;
update(r);
}
}
else
{
for(int i = 1;i <= n;i++) if(a[i] == l) a[i] = r;
update(r);
}
cl(f[l]) , siz[r] += siz[l] , siz[l] = 0;
}
else
{
int l = rel[x] , r = rel[y];
if(!siz[l] || !siz[r]) lastans = -1;
else if(l == r) lastans = 0;
else
{
if(siz[l] > siz[r]) swap(l , r);
if(siz[r] <= len) lastans = calc(f[l] , f[r]);
else if(siz[l] <= len) lastans = min(sum[stk[r]][l] , calc(f[l] , f[r]));
else lastans = min({sum[stk[r]][l] , sum[stk[l]][r] , calc(f[l] , f[r])});
}
if(lastans == -1) puts("Ikaros") , lastans = 0;
else printf("%d\n" , lastans);
}
}
return 0;
}
作者:JiaY19
出处:https://www.cnblogs.com/JiaY19/p/16005691.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)