HDOJ 2688 HDU 2688 Rotate ACM 2688 IN HDU

本文介绍了一道名为“Rotate”的算法题的解决方案,该题要求在整数序列上进行旋转操作,并计算特定条件下整数对的数量。通过预先计算总数和局部调整的方法优化了算法效率。

MiYu原创, 转帖请注明 : 转载自 ______________白白の屋     

题目地址:

http://acm.hdu.edu.cn/showproblem.php?pid=2688

题目描述: 

Rotate

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 250    Accepted Submission(s): 68


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
 

 题目分析:

如果是暴力 , 没一次更新都要重新计算的话,  时间上的开销会非常大.

对数据进行分析,可以看到, 当旋转的时候, 除了 第一个数, 其他的数的对数的个数值都与这个数有关,   因此, 只要开始

先把总的对数 sum 算出来, 再 根据旋转时 每个数跟第一个数的大小 比较 ,对sum 进行更新就可以了.

 

代码如下:

ExpandedBlockStart.gif 代码
/*
MiYu原创, 转帖请注明 : 转载自 ______________白白の屋
          
http://www.cnblog.com/MiYu
Author By : MiYu
Test      : 1
Program   : 2688
*/

#include 
< iostream >
#include 
< algorithm >
using   namespace  std;
const   int  MAX  =   10000 ;
int  nCount  =   0 , N, M, x , y;
int  com[MAX  +   1 ], num[ 300   *  MAX  +   1 ]; 
long   long  sum  =   0
char  ask[ 5 ];
inline 
int  low (  int  x ) {
       
return  x  &  (  - x );
}
void  modify (  int  x,  int  val ){      //  修改 
      while  ( x  <=  MAX ){
            com[x] 
+=  val; x  +=  low ( x );
     }     
}
int  quy (  int  x ){                   //  查询 
     int  sum  =   0 ;
    
while  ( x  >   0  ){
           sum 
+=  com[x]; x  ^=  low ( x );
    }
    
return  sum ;
}
inline 
bool  scan_d( int   & num)       //  输入 
{
        
char   in ; bool  IsN = false ;
        
in = getchar();
        
if ( in == EOF)  return   false ;
        
while ( in != ' - ' && ( in < ' 0 ' || in > ' 9 ' ))  in = getchar();
        
if ( in == ' - ' ){ IsN = true ;num = 0 ;}
        
else  num = in - ' 0 ' ;
        
while ( in = getchar(), in >= ' 0 ' && in <= ' 9 ' ){
                num
*= 10 ,num += in - ' 0 ' ;
        }
        
if (IsN) num =- num;
        
return   true ;
}
int  main ()
{
    
while  ( scan_d ( N ) ){
           memset ( com, 
0 sizeof  ( com ) ); sum  =   0 ;
           
for  (  int  i  =   0 ; i  <  N;  ++  i ){
                scan_d ( num[i] ); modify ( num[i], 
1  ); 
                sum 
+=  quy ( num[i]  -   1  );
           }
           scan_d ( M );
           
while  ( M  --  ){
                  scanf ( 
" %s " ,ask );   int  temp; 
                  
switch  ( ask[ 0 ] ){
                          
case   ' Q '  : cout  <<  sum  <<  endl;  break ;
                          
case   ' R '  : scan_d ( x ), scan_d ( y ); temp  =  num[x];
                                     
while  ( x  <  y ) { num[x]  =  num[x + 1 ]; 
                                             num[x] 
>  temp  ?  sum  --  : num[x]  ==  temp  ? : sum ++  ; x  ++
                                     } 
                                     num[y] 
=  temp;  break ;                             
                  }
           }
    }
    
return   0 ;
}

 

 

 

 

 

转载于:https://www.cnblogs.com/MiYu/archive/2010/08/30/1812690.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值