标签:already print using number ++i ring tin scan 树状数组
for(int i=1;i<=N;++i)
for(int j=N,t;j>i;—j)
if(P[j-1] > P[j])
t=P[j],P[j]=P[j-1],P[j-1]=t;
【题意】求出每个数能到达的最右和最左的坐标之差
【思路】从最后往前跟新到数组中,并且同时求出有多少个数小于当前数,则他所能到的右坐标是当前位置加上右边小于他的数的个数
左坐标是他min(当前位置,a[i])
#include<iostream> #include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> using namespace std; const int N=100000+10; int a[N],sum[N*4],pos[N],res[N]; int n; int lowbit(int p) { return p&(-p); } void update(int p) { while(p<=n) { sum[p]+=1; p+=lowbit(p); } } int get_sum(int p) { int res=0; while(p>0) { res+=sum[p]; p-=lowbit(p); } return res; } int main() { int t,cas=1; scanf("%d",&t); while(t--) { memset(sum,0,sizeof(sum)); scanf("%d",&n); for(int i=1; i<=n; i++) { scanf("%d",&a[i]); pos[a[i]]=i; } for(int i=n; i>0; i--) //倒序,从当前位置右边找出有多少小于他的数,记录在res中,他的最大右坐标是res+pos { update(a[i]); res[a[i]]=get_sum(a[i]-1); } printf("Case #%d: ", cas++); for(int i=1; i<=n; i++) { int minx=min(i,pos[i]); if(i!=n) printf("%d ",abs(pos[i]+res[i]-minx)); else printf("%d\n",abs(pos[i]+res[i]-minx)); } } return 0; }
标签:already print using number ++i ring tin scan 树状数组
原文地址:http://www.cnblogs.com/iwantstrong/p/6075974.html