题目描述
Lyk得到了一个1~n的全排列。Txm每次会交换第i个数和第j个数,对于每次交换,lyk需要回答该全排列的逆序对数为多少。
“1、2、3、4......248289469!”lyk如是回答道。
“最后答案取模2......”
输入
第一行一个数,n
第二行为1~n的某个全排列
第三行一个数m,表示交换操作的次数。
接下来m行,每行两个数i和j
输出
M行,表示m次交换后的答案。
样例输入
4 1 2 3 4 1 1 2
样例输出
1
提示
Constraints
对于30%,n,m<=1000
对于100%,n,m<=100000
归并+暴力线扫忘了a[i]>a[j]时的ans--
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int a[100005],b[100005],A[100005]; long long ans; void merge(int l,int mid,int r) { int i=l;int j=mid+1;int k=l; while(i<=mid&&j<=r) { if(a[i]<=a[j]) b[k++]=a[i++];else ans+=mid-i+1,b[k++]=a[j++]; } for (int p=i;p<=mid;p++) b[k++]=a[p]; for (int p=j;p<=r;p++) b[k++]=a[p]; for(int p=l;p<=r;p++) a[p]=b[p]; } void merge_sort(int l,int r) { if(l==r) return; int mid=(l+r)/2; merge_sort(l,mid); merge_sort(mid+1,r); merge(l,mid,r); } int main() { freopen("lyk.in","r",stdin); freopen("lyk.out","w",stdout); int n,m; ans=0; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) A[i]=a[i]; merge_sort(1,n); scanf("%d",&m); int x,y; long long ANS=ans; for(int i=1;i<=m;i++) { //ans=ANS; scanf("%d %d",&x,&y); if(x>y) swap(x,y); for(int k=x+1;k<=y-1;k++) { if(A[k]>A[x])ans++;else ans--; if(A[k]>A[y])ans--;else ans++; } if(A[x]<A[y]) ans++; //忘了else ans--; swap(A[x],A[y]); printf("%lld ",ans%2); } return 0; }
正解:
每次交换a[i]和a[j]时会对a[i+1..j-1]中的数询问,加上比a[i]大的,减去比a[i]小的;加上比a[j]小的,减去比a[j]大的;最后考虑a[i]和a[j]的大小关系
设分别有z,z1个,则有
ans+=z-(j-i+1-z)+z1-(j-i+1-z1);等价于ans+=2*z+2*z-1-2*(j-i+1)
因为最后询问ans%2 所以改变ans的只有最后一步(考虑a[i]和a[j]的关系)
最后判断i是否等于j
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int a[100005],b[100005],A[100005]; long long ans; void merge(int l,int mid,int r) { int i=l;int j=mid+1;int k=l; while(i<=mid&&j<=r) { if(a[i]<=a[j]) b[k++]=a[i++];else ans+=mid-i+1,b[k++]=a[j++]; } for (int p=i;p<=mid;p++) b[k++]=a[p]; for (int p=j;p<=r;p++) b[k++]=a[p]; for(int p=l;p<=r;p++) a[p]=b[p]; } void merge_sort(int l,int r) { if(l==r) return; int mid=(l+r)/2; merge_sort(l,mid); merge_sort(mid+1,r); merge(l,mid,r); } int main() { //freopen("lyk.in","r",stdin); //freopen("lyk.out","w",stdout); int n,m; ans=0; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) A[i]=a[i]; merge_sort(1,n); ans%=2; scanf("%d",&m); int x,y; for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); if(x!=y) ans=1^ans; printf("%lld ",ans); } return 0; }
还被cout坑了