当前位置: 代码迷 >> 综合 >> POJ 2182 Lost Cows(树状数组,暴力模拟)
  详细解决方案

POJ 2182 Lost Cows(树状数组,暴力模拟)

热度:72   发布时间:2024-01-22 01:52:37.0

题意:

            一数列1-n,顺序为乱序,然后从第二个开始,给出每个元素前面有多少个比该元素小的。求原始数列。

 

题解:

            手动模拟一下怎么还原数列:

从后往前找,弄个标记数组,找就行了,直接暴力。

然而碰到前面有少个比他小这样的字眼,树状数组很快的进行求解。在从后往前的过程中,vis数组存放的已经出现的可以由树状数组求,然后二分去求当前位置的即可。

 

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>using namespace std;
const int maxn = 8011;
int a[maxn],ans[maxn];
bool vis[maxn];
int main()
{int n;while(cin>>n){memset(vis,false,sizeof vis);a[1]=0;for(int i=2; i<=n; i++){scanf("%d",a+i);}ans[n] = a[n]+1;vis[ans[n] ]=true;for(int i=n-1;i>=1;i--){int num = a[i];for(int j=1;j<=n;j++){if(!vis[j])num--;if(num<0){ans[i] = j;vis[j] = true;break;}}}for(int i=1;i<=n;i++)printf("%d\n",ans[i]);}}

 

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>using namespace std;const int maxn = 8011;int c[maxn];
int a[maxn];
int ans[maxn];void add(int x,int v)
{while(x<maxn){c[x]+=v;x+=(x & -x);}
}int sum(int x)
{int res=0;while(x>0){res+=c[x];x-=(x & -x);}return res;
}int main()
{int n;while(cin>>n){memset(c,0,sizeof c);a[1] = 0;for(int i=2;i<=n;i++){scanf("%d",a+i);}ans[n] = a[n]+1;add(ans[n],1);for(int i=n-1;i>=1;i--){int l=0,r=n+1;while(r>l+1){int m = (l+r)>>1;if(sum(m-1)+a[i]+1<m)///sum表示前面已经找出来多少个元素了。相当于暴力里面的vis数组的作用,r=m;else l=m;}ans[i] = l;add(ans[i],1);}for(int i=1;i<=n;i++)printf("%d\n",ans[i]);}
}

 


  相关解决方案