这道题题意很明显,询问序列的顺序数有几对,除此之外有个rotate的操作,对于区间[L,R],rotate操作把当前区间的首位置于末位,并将剩余各位前移一次。
我的解法是用树状数组记录各个数的顺序对数,rotate时采用最朴素的模拟,对于区间[L+1,R]中的数a[i],如果a[i]<a[L],那么总的顺序对数加1,如果a[i]>a[L],总数减1。
这题卡了两周,各种搜题解发现自己的写法并没有什么错误,但就是一直超时,时间卡的还是比较紧的。其实AC代码相对于两周前的代码并没有改进,只是把update和query函数直接写成循环放到了主函数中,最后976ms卡着时间过了。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<functional>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<iostream>
#define Puts puts("pppppppp")
using namespace std;
const int N = 3000005;
const int _max = 10005;
int tree[_max];
int x[N];
__int64 ans;
int lowbit(int x){
return x&(-x);
}
int main(){
int n, m;
while (~scanf("%d", &n)){
ans = 0;
memset(tree, 0, sizeof(tree));
for (int i = 0; i < n; i++){
scanf("%d", &x[i]);
int p1 = x[i] - 1;
while (p1 > 0){
ans += tree[p1];
p1 -= lowbit(p1);
}
int p2 = x[i];
while (p2 <= _max){
tree[p2] ++;
p2 += lowbit(p2);
}
}
scanf("%d", &m);
char ins[5];
int l, r;
for (int i = 0; i < m; i++){
scanf("%s", ins);
if (ins[0] == 'Q'){
printf("%I64d\n", ans);
}
else if (ins[0] == 'R'){
scanf("%d%d", &l, &r);
int temp = x[l];
for (int j = l + 1; j <= r; j++){
if (x[j] < temp)
ans++;
else if (x[j]>temp)
ans--;
x[j - 1] = x[j];
}
x[r] = temp;
}
}
}
return 0;
}