HH:
c++
5
1
2
1
0
2 4 5 3 1
通过长时间的思考(瞎碰),我发现了一件事:
题目翻译成这样:给定每一个点的逆序对的数量,求每一个点。
我和廖半仙一开始进行了愉快的跳表操做。
事实证实它是彻底错的。
总的来讲,这题目被坑了的惟一缘由就是:
MAXN呐!MAXN呐!
+1=100
-1=60
maxn。。。
ANSWER:
我发现:最后一个值是能够肯定的。
由于咱们知道最后一个值前面有几个点比它小,因而这个点就是第n+1大的点。
把这个点塞到答案数组里面。
找前一个大小,咱们发现:删去第一个点,再进行以上操做,就能够获得这个点的大小。
因而:算法确认:
一、找当前数字对应的第a[n]+1大
二、塞答案
三、删去这个数。
重点来了。
咱们删去这个数,怎么实现呢?
若是只要数组硬爆就能解决的事,那仍是wzy大佬出的蓝题吗?
不可能!
我须要一个数据结构,来维护这个东西。
想一想看数据结构们,有什么能够删点呢?删点以后还要把后面的补上来....
我问到了邻接表删点,甚至想到了主席树删点(区间第k小,动态点删掉而后查询便可)
可是....都不行
平衡树吧,有删点操做。
可是我不会。
感谢shy大佬的shy树。
MAXN呐!MAXN呐!
+1=100
-1=60
maxn。。。
上代码:
#include<bits/stdc++.h> using namespace std; const int maxn=1e6; int n,a[maxn],ans[maxn]; struct tree { int ls,rs,size,pre; }t[maxn*2]; int tot=0; int build(int l,int r) { if(l==r) { t[++tot].size=1;//子树大小,叶节点的子树大小=1 t[tot].pre=l;//节点的值=l,12345..... return tot;//返回当前叶节点的编号 } int mid=(l+r)>>1; int x=++tot;//树节点的编号 t[x].ls=build(l,mid);//同主席树建树模式,ls rs=下面的返回值 t[x].rs=build(mid+1,r); t[x].size=r-l+1;//差分处理子树大小 return x; } int ask(int x,int l,int r,int k) { if(l==r) { t[x].size--;//叶节点,删除它 return t[x].pre;//返回叶节点的值 } t[x].size--;//走一条边,删一个点 int mid=l+r>>1; int mik=mid+1; int q=k-t[t[x].ls].size; if(k<=t[t[x].ls].size)return ask(t[x].ls,l,mid,k);//二叉搜索树部分,有点相似主席树,经过差分不停在节点上滑来滑去,直到找到相应的叶节点 else return ask(t[x].rs,mik,r,q); } int main() { scanf("%d",&n); for(int i=2;i<=n;i++) { scanf("%d",&a[i]);//n-1个 } a[1]=0;//第一个数前面没有比它小的 build(1,n);//建树 for(int i=n;i>0;i--) { ans[i]=ask(1,1,n,a[i]+1); } for(int i=1;i<=n;i++) printf("%d\n",ans[i]); return 0; }
思路就是二叉查找树,建树以后,根据a数组,大了往左找,小了往右找,而后找到这个值为止,删点。算法
膜拜shy树数组
%%%shy大佬,tql数据结构
(完)ui