Problem Description
Recently yifenfei face such a problem that give you millions of positive integers,tell how many pairs i and j that satisfy F[i] smaller than F[j] strictly when i is smaller than j strictly. i and j is the serial number in the interger sequence. Of course, the problem is not over, the initial interger sequence will change all the time. Changing format is like this [S E] (abs(E-S)<=1000) that mean between the S and E of the sequece will Rotate one times.
For example initial sequence is 1 2 3 4 5.
If changing format is [1 3], than the sequence will be 1 3 4 2 5 because the first sequence is base from 0.
For example initial sequence is 1 2 3 4 5.
If changing format is [1 3], than the sequence will be 1 3 4 2 5 because the first sequence is base from 0.
Input
The input contains multiple test cases.
Each case first given a integer n standing the length of integer sequence (2<=n<=3000000)
Second a line with n integers standing F[i](0<F[i]<=10000)
Third a line with one integer m (m < 10000)
Than m lines quiry, first give the type of quiry. A character C, if C is ‘R’ than give the changing format, if C equal to ‘Q’, just put the numbers of satisfy pairs.
Each case first given a integer n standing the length of integer sequence (2<=n<=3000000)
Second a line with n integers standing F[i](0<F[i]<=10000)
Third a line with one integer m (m < 10000)
Than m lines quiry, first give the type of quiry. A character C, if C is ‘R’ than give the changing format, if C equal to ‘Q’, just put the numbers of satisfy pairs.
Output
Output just according to said.
Sample Input
5 1 2 3 4 5 3 Q R 1 3 Q
Sample Output
10 8题目大意:给你一个n个数(1到n且不重复)的全排列,求这n个数的正序数(序号比前面大,值也比前面大),然后给出个区间,这个区间顺时针循环转一次。比如,输入R 1 3,下标(从0开始)为1到3的数顺时针循环一次,即(2 3 4 变成3 4 2)其余不动,所以1 2 3 4 5变成 1 3 4 2 5.当输入Q时,输出当前排列的正序数。思路分析:这是一个动态区间更新,求总和问题。由于题目给出是1-n的全排列。所以与求逆序数不同,不要离散化。直接求出正序数即可。更新过程中继续判断.复杂度为n*logN.具体解释 见AC代码。这道题用C++ 提交600MS ,不知为什么一用G++就超时。可能判定系统问题吧。#include<stdio.h> #include<string.h> int a[3000005]; int c[10005]; int n; int lowbit(int x) { return x&(-x); } void updata(int x,int d) { while(x<=10005) /*这点我也是不明白,开始写出 while(x<=n) WA 了无数次 后来才明白题目有这样一句话:Second a line with n integers standing F[i](0<F[i]<=10000),您明白了吗?*/
{ c[x]=c[x]+d; x=x+lowbit(x); } } int getsum(int x) { int res = 0; while(x>0) { res=res+c[x]; x=x-lowbit(x); } return res; } int main() { int m,i; char s[10]; int x,y,t; __int64 ans; while(scanf("%d",&n)!=EOF) { memset(a,0,sizeof(a)); memset(c,0,sizeof(c)); ans = 0; for(i=1; i<=n; i++) { scanf("%d",&a[i]); updata(a[i],1); ans=ans+getsum(a[i]-1); //前a[i]-1个数都比a[i]小,计算总和 } scanf("%d",&m); while(m--) { scanf("%s",s); if(s[0]=='Q') printf("%I64d\n",ans); else { if(s[0]=='R') { scanf("%d%d",&x,&y); x++; //下标从1开始的 y++; t=a[x]; for(i=x; i<y; i++) { //移位过程中,只是a[x]到了a[y]位置,其他都往前进1.相当于没动 //所以,只要把其他数跟a[x]比较即可。 a[i]=a[i+1]; if(a[i]>t) ans--; if(a[i]<t) ans++; } a[y]=t; } } } } return 0; }