思路: 树状数组
分析:
1 题目给定n个数求满足 i < j并且 F[i] < F[j]的个数
2 首先我们可以利用树状数组求出起始序列满足条件的个数sum。那么我们考虑如何把区间[s , e]进行交换,通过题目我们可以知道每一次的交换只是把区间的第一个数换到区间的最后一个位置,那么我们可以考虑假设区间第一个数为x ,区间里比x小的为min,比x大的为max,那么x换到区间的最后一个位置的结果就是原来大于x的数度不能和x构成一对,原来小于x的现在度满足了,那么相当于做一次的变换sum = sum-max+min;
代码:
/************************************************ * By: chenguolin * * Date: 2013-08-22 * * Address: http://blog.csdn.net/chenguolinblog * ***********************************************/ #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef __int64 int64; const int N = 10010; const int MAXN = 3000010; int n; int64 ans; int num[MAXN]; int64 treeNum[N]; int lowbit(int x){ return x&(-x); } int64 getSum(int x){ int sum = 0; while(x){ sum += treeNum[x]; x -= lowbit(x); } return sum; } void add(int x , int val){ while(x < N){ treeNum[x] += val; x += lowbit(x); } } void solve(){ char c; int m , x , y; scanf("%d%*c" , &m); while(m--){ scanf("%c%*c" , &c); if(c == 'Q') printf("%I64d\n" , ans); else{ scanf("%d%d%*c" , &x , &y); x++ , y++; int tmp = num[x]; int min = 0; int max = 0; for(int i = x ; i < y ; i--){ if(num[i] > tmp) max++; if(num[i] < tmp) min++; num[i] = num[i+1]; } if(num[y] > tmp) max++; if(num[y] < tmp) min++; num[y] = tmp; ans = ans+min-max; } } } int main(){ while(scanf("%d" , &n) != EOF){ memset(treeNum , 0 , sizeof(treeNum)); ans = 0; for(int i = 1 ; i <= n ; i++){ scanf("%d" , &num[i]); ans += getSum(num[i]-1); add(num[i] , 1); } solve(); } return 0; }