HDU 1394 역순

4060 단어 DatetreeiniBuild
TLE 코드를 먼저 붙이고...
#include<iostream>
#include<cstdio>
#define MAXN 11111
using namespace std;

int gt[MAXN<<2],st[MAXN<<2];
int date[MAXN];

void pushUpmax( int rt ){
 	 gt[rt]=max(gt[rt<<1],gt[rt<<1|1]);
}
void pushUpmin( int rt ){
 	 st[rt]=min(st[rt<<1],st[rt<<1|1]);
}

void build( int l,int r,int rt )
{
 	 if( l==r )
 	 {
	  	 gt[rt]=st[rt]=date[l];
	  	 return ;
	 }
	 int m=(l+r)/2;
	 build( l,m,rt<<1 );
	 build( m+1,r,rt<<1|1 );
	 pushUpmax(rt);
	 pushUpmin(rt);
}

int querygt( int v,int l,int r,int rt )//        [l,r]     v    。 
{
 	if( l==r )
 		return 0;
 	if( gt[rt]<v )
 		return r-l+1;
	int m=(l+r)/2;
	int ret=0;
	ret+=querygt( v,l,m,rt<<1 );
	ret+=querygt( v,m+1,r,rt<<1|1 );
	return ret;
}

int queryst( int v,int l,int r,int rt )//        [l,r]     v     
{
 	if( l==r )
 		return 0;
 	if( gt[rt]>v )
 		return r-l+1;
	int m=(l+r)/2;
	int ret=0;
	ret+=queryst( v,l,m,rt<<1 );
	ret+=queryst( v,m+1,r,rt<<1|1 );
	return ret;
}

int main()
{
 	int N;
 	while( scanf("%d",&N)!=EOF )
 	{
	 	   for( int i=1;i<=N;i++ )
	 	   {
		   		scanf( "%d",&date[i] );
		   		date[i+N]=date[i];
		   }
		   build(1,2*N,1);
		   int ans=0;
		   for( int i=1;i<=N;i++ )
		   for( int j=i+1;j<=N;j++ )
		   		if( date[i]>date[j] )
		   			ans++;
		   for( int i=1;i<=N;i++ )
		   		ans=min( ans,ans+queryst(date[i],i+1,i+N-1,1)-querygt(date[i],i+1,i+N-1,1) );
		   
		   printf( "%d
",ans ); } return 0; }

TLE는 됐지만 제 시도였어요.TLE가 됐지만...어쩔 수 없이..
먼저 역순수를 정의합니다.
일련의 숫자 시퀀스에서 iAj의 개수입니다.반대로 i>j일 때,Ai통속적으로 말하면Ai가 이전에Ai보다 큰 숫자의 개수이다.
다음은 나의 공식을 간략하게 서술합시다.
|.......|AB|......|
AB가 열에 있는 두 개의 가까운 수라고 가정하고 이 두 개의 수를 위치를 바꾸면 역순수는 어떻게 바뀔까요?
|.......|BA|......|
if(A>B) r--;
if(B>A) r++;
분명히 AB의 위치변경과 좌우 양쪽 이 물건들: |......|네, 괜찮아요.
그럼 A|...||...|로 전환A 는요?
우리는 단계별로 볼 수 있는데..
ABCDEFG
BACDEFG
BCADEFG
BCDAEFG
BCDEAFG
BCDEFAG
BCDEFGA
이렇게 하면 A를 끝까지 옮깁니다.
그렇다면 이 과정의 역서수는 어떻게 바뀌었을까?
A가 증가한 역서수는 [B, G]에서 A보다 큰 것으로 간단하게 추정된다.A가 감소한 역서수는 [B, G]가 A보다 작다.
so... R+=[B, G] 중 A보다 큰 - [B, G]는 A보다 작다.
R은 원래 역수입니다.
이게 위 코드의 유래야..
안타깝게도 TLE가 나왔습니다..
제목에는 특수한 성질이 있다.숫자는 N개가 [0, N-1]로 각각 하나씩 있다.
그래서 Ai를 끝까지 옮겼는데 그 중에서 Ai보다 큰 것은 (N-Ai-1)개, 작은 것은 Ai개가 있었다.
R+=(N-Ai-1)-Ai;
이것이 바로 변화의 공식이다.
so...
폭력으로 하자...
#include<iostream>
using namespace std;

int main()
{
 	int N;
 	while( scanf( "%d",&N )!=EOF )
 	{
	 	   int date[5555],ans=0;
	 	   for( int i=0;i<N;i++ )
	 	   		scanf( "%d",&date[i] );
	 	   for( int i=0;i<N;i++ )
	 	   for( int j=0;j<i;j++ )
	 	   		if( date[j]>date[i] )
	 	   			ans++;
	 	   int temp=ans;
	 	   for( int i=0;i<N;i++ )
	 	   {
		   		temp=temp-date[i]+(N-date[i]-1);
	 	   		ans=min( ans,temp );
		   }
	 	   printf("%d
",ans ); } return 0; }

트리 배열:
#include<iostream>
using namespace std;

int tree[5555],N;

void update( int pt,int v )
{
 	 while( pt<=N )
 	 {
	  		tree[pt]+=v;
	  		pt+=pt&(-pt);
	 }
}

int find( int pt )
{
 	int ret=0;
 	while( pt ) 
	{
 	 	   ret+=tree[pt];
 	 	   pt-=pt&(-pt);
    }
 	return ret;
}

int main()
{
 	int date[5555];
 	while( scanf("%d",&N)!=EOF )
 	{
	 	   memset( tree,0,sizeof(tree) );
	 	   for( int i=0;i<N;i++ )
	 	   {
	 	   		scanf( "%d",&date[i] );
	 	   		date[i]++;
		   }
	 	   int ans=0;
		   for( int i=N-1;i>=0;i-- )
	 	   {
		   		ans+=find(date[i]);
		   		update(date[i],1);
		   }
		   printf( "%d
",ans ); int temp=ans; for( int i=0;i<N;i++ ) { date[i]--; temp=temp-date[i]+(N-date[i]-1); ans=min(temp,ans); } printf( "%d
",ans ); } return 0; }

좋은 웹페이지 즐겨찾기