传送门:http://codeforces.com/problemset/problem/911/D
题意:
给定一个序列,有m次操作,每次操作选取一个区间,将所有的数翻转,每次操作之后输出整个序列的逆序对个数的奇偶
分析:
由于m特别大,没办法用暴力求出逆序对的个数,而且题目也没有要求逆序对的个数,而是要求逆序对的奇偶,这给了我们一点思考,翻转之后的奇偶性由什么决定
题解:
首先假设一开始的时候,整个数列的逆序对个数为 tot t o t 个
当我翻转一个区间[l,r],设这个区间原来的逆序对个数为 x x ,翻转之后逆序对个数为个
那么整个序列的逆序对个数为 tot−x+C2(r−l+1)−x=tot−2x+C2(r−l+1) t o t − x + C ( r − l + 1 ) 2 − x = t o t − 2 x + C ( r − l + 1 ) 2
2x 2 x 对 tot t o t 的奇偶性没有影响,那么 tot t o t 的奇偶性取决于 C2(r−l+1) C ( r − l + 1 ) 2 的奇偶性
(1)如果 C2(r−l+1) C ( r − l + 1 ) 2 为偶数,对 tot t o t 的奇偶性没有影响
(2)如果 C2(r−l+1) C ( r − l + 1 ) 2 为奇数, tot t o t 的奇偶性进行翻转
代码:
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int s[1550];
int main()
{
int n,m;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&s[i]);
}
int cnt=0;
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
if(s[j]<s[i])
cnt++;
}
}
scanf("%d",&m);
cnt%=2;
for(int i=0;i<m;i++)
{
int l,r;
scanf("%d%d",&l,&r);
int x=r-l+1;
if(x*(x-1)/2%2==1) cnt^=1;
if(cnt) printf("odd\n");
else printf("even\n");
}
return 0;
}