H - Rotate HDU - 2688(树状数组水题)

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

题意:最近yifenfei面临这样一个问题,给你数百万的正整数,当i小于j时,严格地告诉我有多少对i和j满足F [i]小于F [j]。i和j是整数序列中的序列号。当然,问题还没有结束,最初的整数序列将一直在变化。改变格式就像这个[SE](abs(ES)<= 1000),它意味着在序列的S和E之间旋转一次。 
例如,初始序列是1 2 3 4 5. 
如果改变格式是[1 3],则序列将是1 3 4 2 5,因为第一个序列是从0开始的。 

旋转的意思是将该区间的最前面的一个放在这个区间的最后一个。然后前面的数字依次往前面动就可以了。这题目就是开一个sum[10000]跑一次记录正序对数组。总的正序对为ans。当旋转[S,E]时候只需要维护[S,E]区间就可以了。遇到比W[S]大的ans--

。遇到比W[S]小的就ans++。最后遇到Q就输出ans就可以了

还有注意的一个点事。10000平方会超过int,所以要使用long long

#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <string>
#include <iostream>
using namespace std;
int n=10001;
long long C[10001];
long long M[3003000];
long long lowbit(int i)
{
    return i&-i;
}
void update(int i,int val)
{
    while(i<=n)
    {
        C[i]=C[i]+val;
        i=i+lowbit(i);
    }
}
long long sum(int i)
{
    long long ret=0;
    while(i>0)
    {
        ret=ret+C[i];
        i=i-lowbit(i);
    }
    return ret;
}
void init()
{
    memset(C,0,sizeof(C));
    memset(M,0,sizeof(M));
}
int main()
{
    int k;
    string s;
    while(scanf("%d",&k)!=EOF)
    {
        init();
        long long ans=0;
        for(int i=0;i<k;i++)
        {
            scanf("%lld",&M[i]);
            ans=ans+sum(M[i]-1);
            update(M[i],1);
        }
        int q;
        scanf("%d",&q);
        for(int i=1;i<=q;i++)
        {
            cin>>s;
            if(s=="Q") 
                printf("%lld\n",ans);
            else
            {
                int f,e,temp;
                scanf("%d %d",&f,&e);
                temp=M[f];
                for(int j=f+1;j<=e;j++)
                {
                    M[j-1]=M[j];
                    if(temp>M[j])
                        ans++;
                    else if(temp<M[j])
                        ans--;
                }
                M[e]=temp;
            }
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值