根号分治入门
根号分治
思想概述
根号分治,是应对序列问题的方法。对于一个序列问题,设置阀值
[CCO2021] Swap Swap Sort
题目描述
你有一个长度为
你的朋友发明了一个排序算法,可以根据一个
例如,序列为
你对你朋友的排序算法在目标排列不同时执行 swap 的次数很感兴趣。为了研究其中的规律,你一开始将目标排列设置为
输入格式
第一行,三个整数
第二行,
接下来
输出格式
对于每次询问,输出一个整数,表示所求的值。
样例 #1
样例输入 #1
5 4 3
1 4 2 1 2
3
2
1
样例输出 #1
4
2
2
对于
题解
首先,考虑目标排列是
接着考虑将两个数
可以这样等效考虑,在目标情况中对两个数互换,等价于在排序后的序列中将
所以因为
而交换两数位置,只会有:
因为
设阀值为
对于一组询问vector
存储每个数出现的位置,双指针扫描一遍,复杂度
总复杂度
不过在处理第一种情况的时候,由于空间复杂度为
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;
#define N 100050
#define Q 1000500
#define int long long
struct node{
int x,y,id,tag;
};
vector<node>t[N];
vector<int>seat[N];
int n,m,k,q,s=100,c[N],ans,b[N],a[N],cnt1[N],cnt2[N],c1[N],Ans[Q],f[N],vis[N];
#define lowbit(x) x&-x
void add(int x,int k1){
for(int i=x;i<=k;i+=lowbit(i))c1[i]+=k1;
}
int ask(int x){
int ans=0;
for(int i=x;i;i-=lowbit(i))ans+=c1[i];
return ans;
}
int get(int x,int y){//h(x,y)
int ans=0;
int l=0,r=0,len1=seat[x].size(),len2=seat[y].size();
for(r=0;r<len2;r++){
while(seat[x][l]<seat[y][r]&&l<len1)l++;
ans+=l;
}
return (c[x]*c[y]-2*ans);
}
void init(){
cin>>n>>k>>q;
s=n/sqrt(q)+3;
for(int i=1;i<=k;i++)b[i]=i;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)seat[a[i]].push_back(i);
for(int i=1;i<=n;i++)c[a[i]]++;
for(int i=n;i;--i){
ans+=ask(a[i]-1);
add(a[i],1);
}
for(int i=1;i<=q;i++){
int xb;
cin>>xb;
swap(b[xb],b[xb+1]);
int x=b[xb],y=b[xb+1];
if(c[x]<s&&c[y]<s){
if(c[x]==0||c[y]==0)Ans[i]=0;
else Ans[i]=get(x,y);
}
else {
if(c[x]<s)t[y].push_back((node){y,x,i,-1});
else t[x].push_back((node){x,y,i,1});
}
}
for(int i=1;i<=n;i++){//h(a[i],a[j])
if(c[a[i]]<s||vis[a[i]])continue;
memset(f,0,sizeof f);
int cnt1=0;
for(int j=1;j<=n;j++){
if(a[j]==a[i])cnt1++;
else{
f[a[j]]+=cnt1;
}
}
vis[a[i]]=1;
int len1=t[a[i]].size();
for(int j=0;j<len1;j++){
Ans[t[a[i]][j].id]=t[a[i]][j].tag*(c[t[a[i]][j].x]*c[t[a[i]][j].y]-2*f[t[a[i]][j].y]);
}
}
for(int i=1;i<=q;i++){
ans+=Ans[i];
cout<<ans<<endl;
}
}
signed main(){
// freopen("data.in","r",stdin);
// freopen("data.ans","w",stdout);
ios::sync_with_stdio(false);
init();
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!