Rotate(数状数组+逆序数)

Problem C

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 113   Accepted Submission(s) : 14
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.
 

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.
 

Output
Output just according to said.
 

Sample Input
  
  
5 1 2 3 4 5 3 Q R 1 3 Q
 

Sample Output
  
  
10 8
 

Statistic |  Submit |  Back

题意:

共n个数,m次操作,Q表示询问n个数有多少顺序数,R a,b表示区间[a,b]中的数转动一下(a+1~b每个数向前移动,a位置的数到b位置).

思路:

如果每询问一次就求一次顺序数很费时间,先求出最初的顺序数ans,每转动一次时如果a+1~b位置的数大于a位置的数,ans--,如果小于a,ans++,那么就用到了数状数组求逆序数

代码:

#include<cstring>  
#include<cstdio>  
#include<iostream>  
#include<algorithm>  
#include<cstdlib>  
#include<map>
#include<vector>
#define maxn 10005
#define M 3000010
#define ll long long 
using namespace std;
int tree[maxn];
int num[M]; 
int lowbit(int x){
	return x&-x;
}

void update(int i,int v) {  
    while(i<maxn) {  
        tree[i]+=v;  
        i+=lowbit(i);  
    }  
}

ll getsum(int i) {
    ll s=0;
    while(i>0) {  
        s+=tree[i];  
        i-=lowbit(i); 
    }
    return s;  
}
  
int main() {  
	int n,m;
	int i,j;
	int x,y;
	char str[10];
	ios::sync_with_stdio(false);
	while(cin>>n){
		ll ans=0;
		memset(tree,0,sizeof(tree));
		for(i=0;i<n;i++){
			cin>>num[i];
			ans+=getsum(num[i]-1);//nixushu
			update(num[i],1);	
		}
		cin>>m;
		while(m--){
			cin>>str;
			if(str[0]=='Q'){
				cout<<ans<<endl;
			}
			else{
				cin>>x>>y;
				int s=num[x];
				for(i=x;i<y;i++){
					num[i]=num[i+1];
					if(s<num[i]){
						ans--;
					}
					if(s>num[i]){
						ans++;
					}
				}
				num[y]=s;
			}
		}
	}
    return 0;  
}  





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值