联合省选 R5
https://cplusoj.com/d/senior/contest/69a400fc1363e1a076945687
T1
诈骗题,注意到一个数 \(+k\) 和 \(-k\) 的奇偶性相同,所以我们直接将这个数含有的所有奇数数量的元素异或起来,计做 \(s[x]\),考虑加法操作就是两个 \(s\) 异起来,第1、3的操作都是如果 \(k\) 是奇数,就异或上,否则不变。
Code
#include<bits/stdc++.h>
using namespace std;
namespace IO{
#define gc getchar
#define pc putchar
#define ps puts
inline int in(){
int x=0,f=1;
char c=gc();
for(;!isdigit(c);c=gc())if(c=='-')f=-1;
for(;isdigit(c);c=gc())x=x*10+(c-'0');
return x*f;
}
inline void out(int x){
if(x<0)pc('-'),x=-x;
if(x>=10)out(x/10);
pc(x%10+'0');
}
inline void outsp(int x){out(x),pc(' ');}
inline void outln(int x){out(x),ps("");}
}
using namespace IO;
const int N=1e6+5;
int n,q,s[N];
int main(){
freopen("silent.in","r",stdin);
freopen("silent.out","w",stdout);
q=in();int lst=0;
while(q--){
int opt=in()^lst;
if(opt==1){
int m=in()^lst,k=in()^lst;
s[++n]=k&1?m:0;
}
if(opt==2){
int x=in()^lst,y=in()^lst;
s[++n]=s[x]^s[y];
}
if(opt==3){
int x=in()^lst,m=in()^lst,k=in()^lst;
s[++n]=s[x]^(k&1?m:0);
}
if(opt==4)outln(s[in()]);
}
return 0;
}
T3
诈骗题,考虑从正序排列开始调整,这样逆序对数就是交换次数。然后,如果不存在 \(a_i=i\),那么答案就是0,接着考虑将这些 \(i\) 移走。对于所有这种 \(i\),设 \([L_i,R_i]\) 为极长的 \(a_i\) 的连续段,然后可以移到 \(L_i-1\) 或 \(R_i+1\),还有一种corner case,就是当存在 \(R_j+1=L_i\) 时,先动 \(j\) 再动 \(i\) 可以比分开少一步。然后就直接dp就行。
Code
#include<bits/stdc++.h>
using namespace std;
namespace IO{
#define gc getchar
#define pc putchar
#define ps puts
inline int in(){
int x=0,f=1;
char c=gc();
for(;!isdigit(c);c=gc())if(c=='-')f=-1;
for(;isdigit(c);c=gc())x=x*10+(c-'0');
return x*f;
}
inline void out(int x){
if(x<0)pc('-'),x=-x;
if(x>=10)out(x/10);
pc(x%10+'0');
}
inline void outsp(int x){out(x),pc(' ');}
inline void outln(int x){out(x),ps("");}
}
using namespace IO;
const int N=2e5+5;
int t,n,m,a[N],b[N],L[N],R[N],gap[N],p[N],f[N];
void dfs(int x){
if(!x)return;
dfs(x-gap[x]);
int y=b[x];
if(gap[x]==1){
if(R[x]>n||(L[x]&&y-L[x]<R[x]-y))rotate(p+L[x],p+y,p+y+1);
else rotate(p+y,p+y+1,p+R[x]+1);
}
else{
rotate(p+L[x]+1,p+y,p+y+1),rotate(p+b[x-1],p+b[x-1]+1,p+R[x-1]);
swap(p[L[x]],p[L[x]+1]);
}
}
int main(){
freopen("inversion.in","r",stdin);
freopen("inversion.out","w",stdout);
t=in();
while(t--){
n=in(),m=0;
for(int i=1;i<=n;i++)a[i]=in(),p[i]=i,gap[i]=0;
for(int i=1;i<=n;i++)if(a[i]==i)b[++m]=i;
for(int i=1;i<=m;i++){
int x=b[i];
L[i]=R[i]=x;
while(L[i]>=1&&a[L[i]]==a[x])L[i]--;
while(R[i]<=n&&a[R[i]]==a[x])R[i]++;
}
if(m&&L[1]==0&&R[1]==n+1){outln(-1);continue;}
f[0]=0;
for(int i=1;i<=m;i++){
int x=b[i];
f[i]=f[i-1]+min(L[i]>=1?x-L[i]:N,R[i]<=n?R[i]-x:N),gap[i]=1;
if(i>1&&R[i-1]==L[i]+1){
int w=f[i-2]+R[i-1]-b[i-1]+x-L[i]-1;
if(w<f[i])f[i]=w,gap[i]=2;
}
}
dfs(m);
for(int i=1;i<=n;i++)outsp(p[i]);
ps("");
}
return 0;
}
```cpp
浙公网安备 33010602011771号