Zamjene
主要难点在读题。首先理清所谓“可交换集”的意义。可交换集是对于下标而言的,,每个可交换集是一个数对,相当于是把数列中的两个位置连接了起来,而所有可以通过这些边到达的下标集合被称为一片云。一片云是好的当且仅当云中对应下标在原数列中组成的集合和排序后对应下标组成的集合完全相同。很显然假如一片云是好的,那么这片云中的任意元素都可以通过一些方式到达排序后的对应位置,所以一个序列可以通过“可交换集”变成有序序列当且仅当所有云都是好的。既然如此,可以把每一片云当成一个集合,每个操作
考虑如何优化。发现上面那个算法中操作
代码不够精简,见谅。
#include<bits/stdc++.h>
//#define feyn
#define int long long
using namespace std;
const int N=1000010;
const int S=1e9;
const int P[3]={S+7,S+9,S+11};
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
wh*=f;return;
}
struct node{int a[3];};
inline void swap(node &s1,node &s2){node s3=s1;s1=s2;s2=s3;return;}
inline bool operator <(node s1,node s2){
for(register int i=0;i<3;i++){
if(s1.a[i]^s2.a[i])return s1.a[i]<s2.a[i];
}
return false;
}
inline bool operator !=(node s1,node s2){
for(register int i=0;i<3;i++){
if(s1.a[i]^s2.a[i])return true;
}
return false;
}
inline bool operator ==(node s1,node s2){
for(register int i=0;i<3;i++){
if(s1.a[i]^s2.a[i])return false;
}
return true;
}
inline node operator +(node s1,node s2){
for(register int i=0;i<3;i++){
s1.a[i]=(s1.a[i]+s2.a[i])%P[i];
}
return s1;
}
inline node operator -(node s1,node s2){
for(register int i=0;i<3;i++){
s1.a[i]=(s1.a[i]-s2.a[i]+P[i])%P[i];
}
return s1;
}
inline node _(node s1){
for(register int i=0;i<3;i++){
s1.a[i]=P[i]-s1.a[i];
}
return s1;
}
inline node make(int wh){
node an=(node){1,1,1};
for(int i=0;i<3;i++){
for(int j=1;j<=12;j++)an.a[i]=an.a[i]*wh%P[i];
}
return an;
}
node a[N],b[N],fir_a[N],fir_b[N];
//b[i]:after sorted seq
int m,n,vv[N];
int f[N],size[N];
int not_same;//不好的云的个数
inline void ss_insert(int wh){if(a[wh]!=b[wh])not_same++;}
inline void ss_del(int wh){if(a[wh]!=b[wh])not_same--;}
int ans_sec;//第二种询问的方案数
map<node,int>mp;
inline void mp_insert(int wh){
if(a[wh]==b[wh])return;
node data=a[wh]-b[wh];
ans_sec+=mp[_(data)]*size[wh];
mp[data]+=size[wh];
}
inline void mp_del(int wh){
if(a[wh]==b[wh])return;
node data=a[wh]-b[wh];
mp[data]-=size[wh];
ans_sec-=mp[_(data)]*size[wh];
}
inline int find(int wh){
return f[wh]==wh?wh:f[wh]=find(f[wh]);
}
inline void merge(int x,int y){
x=find(x),y=find(y);
if(x==y)return;
f[y]=x;
mp_del(x);mp_del(y);
ss_del(x);ss_del(y);
size[x]+=size[y];
a[x]=a[x]+a[y],b[x]=b[x]+b[y];
mp_insert(x);
ss_insert(x);
}
inline void swap_pl(int x,int y){
int fx=find(x),fy=find(y);
if(fx==fy){
swap(fir_a[x],fir_a[y]);
return;
}
ss_del(fx);ss_del(fy);
mp_del(fx);mp_del(fy);
a[fx]=a[fx]-fir_a[x]+fir_a[y];
a[fy]=a[fy]-fir_a[y]+fir_a[x];
ss_insert(fx);ss_insert(fy);
mp_insert(fx);mp_insert(fy);
swap(fir_a[x],fir_a[y]);
}
signed main(){
#ifdef feyn
freopen("in.txt","r",stdin);
#endif
read(m);read(n);
for(int i=1;i<=m;i++){
read(vv[i]);a[i]=fir_a[i]=make(vv[i]);
}
sort(vv+1,vv+m+1);
for(int i=1;i<=m;i++){
b[i]=fir_b[i]=make(vv[i]);f[i]=i;size[i]=1;
ss_insert(i);mp_insert(i);
}
int op,x,y;
while(n--){
read(op);
if(op==1){
read(x);read(y);
swap_pl(x,y);
}
if(op==2){
read(x);read(y);
merge(x,y);
}
if(op==3){
if(not_same==0)printf("DA\n");
else printf("NE\n");
}
if(op==4){
printf("%lld\n",ans_sec);
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具