打卡信奥刷题(3235)用C++实现信奥题 P8449 [LSOT-1] 逆序对
·
P8449 [LSOT-1] 逆序对
题目背景
逆序对真好玩
题目描述
你需要维护一个数列,支持以下 444 种操作:
- 区间交换;
- 把一个区间向后移动到第 kkk 个数字与第 k+1k+1k+1 个数字之间;
- 在最后插入一个数 xxx;
- 在开头插入一个数 xxx。
每个数数的序号为新序列重新从第一个数到第 kkk 个数编号为 111 到 kkk。
现在每次操作过后,请你输出整个数列逆序对数量的奇偶性。
输入格式
第一行输入两个正整数 n,mn,mn,m,表示初始序列的长度与操作个数。
接下来一行输入 nnn 个正整数 a1,a2,…,ana_1,a_2,\dots,a_na1,a2,…,an,表示初始序列。
接下来 mmm 行,每行先输入一个 ttt 表示操作编号,之后:
- 若 t=1t=1t=1,则输入四个正整数 l1,r1,l2,r2l_1,r_1,l_2,r_2l1,r1,l2,r2,表示将区间 [l1,r1][l_1,r_1][l1,r1] 与区间 [l2,r2][l_2,r_2][l2,r2] 整体交换,保证 l1≤r1<l2≤r2l_1\le r_1< l_2\le r_2l1≤r1<l2≤r2;
- 若 t=2t=2t=2,则输入三个正整数 l,r,kl,r,kl,r,k,表示将区间 [l,r][l,r][l,r] 移动至序列的第 kkk 个数与第 k+1k+1k+1 个数之间,保证 r<kr<kr<k;
- 若 t=3t=3t=3,则输入一个正整数 xxx,表示将 xxx 插入到序列末端;
- 若 t=4t=4t=4,则输入一个正整数 xxx,表示将 xxx 插入到序列首端。
输出格式
对于每一个指令执行后,如果逆序对数量是偶数,请输出 even ,否则输出 odd。
输入输出样例 #1
输入 #1
6 4
4 3 5 7 2 6
1 1 1 2 2
2 1 1 3
3 11
4 1
输出 #1
odd
odd
odd
odd
说明/提示
【样例解释】
第一次操作将区间 [1,1][1,1][1,1] 和区间 [2,2][2,2][2,2] 交换,序列变为 3 4 5 7 2 6。
第二次操作将区间 [1,1][1,1][1,1] 移动到第 333 和第 444 个数中间。序列变为 4 5 3 7 2 6。
第三次操作在序列末端插入 111111,序列变为 4 5 3 7 2 6 11。
第四次操作在序列开头插入 111,序列变为 1 4 5 3 7 2 6 11。
【数据范围】
「本题采用捆绑测试」
- Subtask 1(10 pts): n,m≤102\texttt{Subtask 1(10 pts): }n,m\le 10^2Subtask 1(10 pts): n,m≤102;
- Subtask 2(15 pts): n,m≤103\texttt{Subtask 2(15 pts): }n,m\le 10^3Subtask 2(15 pts): n,m≤103;
- Subtask 3(20 pts): \texttt{Subtask 3(20 pts): }Subtask 3(20 pts): 没有一二操作;
- Subtask 4(20 pts): \texttt{Subtask 4(20 pts): }Subtask 4(20 pts): 没有三四操作;
- Subtask 5(35 pts): \texttt{Subtask 5(35 pts): }Subtask 5(35 pts): 无特殊限制。
对于 100%100\%100% 的数据,1≤n,m≤2×105,ai≤2×1061\le n,m \le 2\times 10^5,a_i\le 2\times10^61≤n,m≤2×105,ai≤2×106,保证在任意时刻 aaa 中的数均互不相同。
C++实现
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=2000004;
int res,n,m,a,tr[maxn];
void add(int p,int v){
while(p<=maxn-2){
tr[p]+=v;
p+=p&-p;
}
}
int sum(int p){
int ret=0;
while(p){
ret+=tr[p];
p-=p&-p;
}
return ret;
}
signed main(){
scanf("%lld %lld",&n,&m);
for(int i=1;i<=n;i++){
scanf("%lld",&a);
res^=sum(maxn-2)-sum(a);
add(a,1);
}
while(m--){
int op,k,l1,r1,l2,r2,n1,n2,N,x;
scanf("%lld",&op);
if(op==1){
scanf("%lld %lld %lld %lld",&l1,&r1,&l2,&r2);
n1=r1-l1+1,n2=r2-l2+1,N=l2-r1-1;
res^=N*(n1+n2)+n1*n2;
}
if(op==2){
scanf("%lld %lld %lld",&l1,&r1,&k);
n1=r1-l1+1,n2=k-r1;
res^=n1*n2;
}
if(op==3){
scanf("%lld",&x);
res^=sum(maxn-2)-sum(x);
add(x,1);
}
if(op==4){
scanf("%d",&x);
res^=sum(x);
add(x,1);
}
puts(res&1?"odd":"even");
}
return 0;
}

后续
接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容
更多推荐


所有评论(0)