这是一道看似复杂其实也不简单的思维题。
其实思路很明显。
因为这道题的数据范围比较大,有1e5的询问,如果暴力(像我考场上那样打平衡树)的话可以做到$mnlogn$。
但那样也是稳T。
经过思考之后我们可以发现,这道题必定要使用m的解法,也就是对于每一个询问$O1$求解。(总不可能$mlogn$求解)
那么怎么$O1$呢?
众所周知,$O1$算法自古以来就和数学脱不开关系。
而本题中有哪些量可以扯上来搞一搞呢?
具体的值?肯定不现实。
那也就只剩下区间长度了。
针对区间长度进行考察之后,我们可以发现这样的一件事:
如果区间中数对个数为偶数,那么翻转之后答案不变。
否则变化。
这是为什么呢?
很显然,翻转操作是具有封闭性的。换言之,不会影响到外面的元素。
而根据我们的手动模拟,翻转后逆序对个数=数对数-翻转前逆序对个数。
于是乎正解就出来了。
我们先用树状数组搞一搞原数组的逆序对。
然后对于每一组询问,异或一下判奇偶即可。
AC代码如下:
797ms 24kb
1 // By Ilverene 2 3 #include<bits/stdc++.h> 4 5 using namespace std; 6 7 namespace StandardIO{ 8 9 template<typename T>inline void read(T &x){ 10 x=0;T f=1;char c=getchar(); 11 for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1; 12 for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0'; 13 x*=f; 14 } 15 16 template<typename T>inline void write(T x){ 17 if(x<0)putchar('-'),x*=-1; 18 if(x>=10)write(x/10); 19 putchar(x%10+'0'); 20 } 21 22 } 23 24 using namespace StandardIO; 25 26 namespace Solve{ 27 28 // Define your constants here. 29 const int N=1515; 30 31 // Define your global variables here. 32 int n,m,s=0,a[N],b[N]; 33 // Define your main functions here. 34 template<typename _Tp>inline _Tp query(_Tp x){ 35 int res=0; 36 for(int i=x;i;i-=i&-i)res+=b[i]; 37 return res; 38 } 39 void update(int x){ 40 for(int i=x;i<=n;i+=i&-i)++b[i]; 41 } 42 43 inline void solve(){ 44 // Write your main logic here. 45 read(n); 46 for(int i=1;i<=n;++i)read(a[i]); 47 for(int i=n;i>=1;--i){ 48 s=(s+query(a[i]-1))&1; 49 update(a[i]); 50 } 51 read(m); 52 while(m--){ 53 int l,r; 54 read(l),read(r); 55 if(((r-l+1)*(r-l)/2)&1)s^=1,printf(s?"odd":"even"); 56 else printf(s?"odd":"even"); 57 putchar(' '); 58 } 59 } 60 } 61 62 using namespace Solve; 63 64 int main(){ 65 // freopen(".in","r",stdin); 66 // freopen(".out","w",stdout); 67 solve(); 68 }