HDU 1394 역순
#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가 됐지만...어쩔 수 없이..
먼저 역순수를 정의합니다.
일련의 숫자 시퀀스에서 i
다음은 나의 공식을 간략하게 서술합시다.
|.......|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;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JS_3. 내장객체Math는 전역객체이기 때문에 new 키워드 사용하지 않음 new Object() 대신 { } 사용가능 new Array() 대신 [ ] 사용가능 new String()대신 " " 사용가능 new Boolean()대...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.