NC222132. 逆序对
描述
我们称逆序对为一个序列中满足 且 的二元组 。
若一个排列的逆序对个数为奇数,则称它为一个奇排列,否则它被称为偶排列。
给出一个长度为 的排列,有 种操作:
对一个长度为 的序列的操作定义如下:
注意上述定义中同一个操作内的移动都是同时进行的。
小 想要知道每次操作之后这个排列是奇排列还是偶排列。
输入描述
第一行两个整数 ,表示序列的长度和操作的次数。
第二行 个整数,表示一个 至 的排列。
接下来 行,每行三或四个整数,表示一次操作,具体格式及其含义见题目描述。
输出描述
共 行表示每次操作后的答案,若为奇排列则输出 ,若为偶排列则输出 。
示例1
输入:
5 5 1 2 3 4 5 1 1 3 1 2 3 2 2 5 3 1 2 1 4 3 5 1
输出:
1 0 0 1 1
说明:
原排列的逆序对个数为 。示例2
输入:
10 10 1 4 3 5 2 9 8 6 7 10 1 2 3 2 3 5 4 3 7 2 2 3 5 3 5 7 4 1 2 6 4 1 10 6 3 2 4 3 1 3 4 2 3 9
输出:
0 1 1 0 0 1 1 1 0 1
说明:
C++ 解法, 执行用时: 217ms, 内存消耗: 2936K, 提交时间: 2021-06-05 20:09:45
#include<bits/stdc++.h> #define N 1000005 using namespace std; int n,a[N],m,ans,t[N]; void add(int x){ for(;x<=n;x+=x&-x)t[x]^=1; } int sum(int x){ int res=0; for(;x;x-=x&-x)res^=t[x]; return res; } int main(){ cin>>n>>m; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } for(int i=n;i>=1;i--){ ans^=sum(a[i]); add(a[i]); } while(m--){ int op,l,r,k; scanf("%d%d%d",&op,&l,&r); if(op>2)scanf("%d",&k); if(op==1)ans^=1; else if(op==2)ans^=((r-l+1)/2)&1; else if(op>2)ans^=(k*(r-l+1-k))&1; cout<<ans<<"\n"; } }