ACM___________________________

______________白白の屋
posts - 182, comments - 102, trackbacks - 0, articles - 0

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 进行更新就可以了.

 

代码如下:

代码
/*
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, 
0sizeof ( 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;
}

 

 

 


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理