生活随笔
收集整理的這篇文章主要介紹了
[蓝桥杯][2016年第七届真题]压缩变换(主席树求区间不同数的个数)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目描述
小明最近在研究壓縮算法。
他知道,壓縮的時候如果能夠使得數值很小,就能通過熵編碼得到較高的壓縮比。
然而,要使數值很小是一個挑戰。
最近,小明需要壓縮一些正整數的序列,這些序列的特點是,后面出現的數字很大可能是剛出現過不久的數字。對于這種特殊的序列,小明準備對序列做一個變換來減小數字的值。
變換的過程如下:
從左到右枚舉序列,每枚舉到一個數字,如果這個數字沒有出現過,剛將數字變換成它的相反數,如果數字出現過,則看它在原序列中最后的一次出現后面(且在當前數前面)出現了幾種數字,用這個種類數替換原來的數字。
比如,序列(a1, a2, a3, a4, a5)=(1, 2, 2, 1, 2)在變換過程為:
a1: 1未出現過,所以a1變為-1;
a2: 2未出現過,所以a2變為-2;
a3: 2出現過,最后一次為原序列的a2,在a2后、a3前有0種數字,所以a3變為0;
a4: 1出現過,最后一次為原序列的a1,在a1后、a4前有1種數字,所以a4變為1;
a5: 2出現過,最后一次為原序列的a3,在a3后、a5前有1種數字,所以a5變為1。
現在,給出原序列,請問,按這種變換規則變換后的序列是什么。
輸入
輸入第一行包含一個整數n,表示序列的長度。
第二行包含n個正整數,表示輸入序列。
輸出
輸出一行,包含n個數,表示變換后的序列。
樣例輸入
5
1 2 2 1 2
樣例輸出
-1 -2 0 1 1
思路:這個題目我不知道有沒有別的做法,但是主席樹是可以做的。這算是一個求區間不同數的個數的模板題了。注意區間端點的取值。
代碼如下:
#include<bits/stdc++.h>
#define ll long long
using namespace std
;const int maxx
=1e5+100;
struct node{int l
,r
,sum
;
}p
[maxx
*40];
int root
[maxx
*40];
int a
[maxx
];
int n
,rot
=0;inline int build(int l
,int r
)
{int cur
=++rot
;p
[cur
].sum
=0;p
[cur
].l
=p
[cur
].r
=0;if(l
==r
) return cur
;int mid
=l
+r
>>1;p
[cur
].l
=build(l
,mid
);p
[cur
].r
=build(mid
+1,r
);return cur
;
}
inline int update(int pos
,int lrot
,int v
,int l
,int r
)
{int cur
=++rot
;p
[cur
]=p
[lrot
];p
[cur
].sum
+=v
;if(l
==r
) return cur
;int mid
=l
+r
>>1;if(pos
<=mid
) p
[cur
].l
=update(pos
,p
[lrot
].l
,v
,l
,mid
);else p
[cur
].r
=update(pos
,p
[lrot
].r
,v
,mid
+1,r
);return cur
;
}
inline int query(int pos
,int lrot
,int l
,int r
)
{if(l
==r
) return p
[lrot
].sum
;int mid
=l
+r
>>1;if(pos
<=mid
) return p
[p
[lrot
].r
].sum
+query(pos
,p
[lrot
].l
,l
,mid
);else return query(pos
,p
[lrot
].r
,mid
+1,r
);
}
int main()
{scanf("%d",&n
);map
<int,int> mp
;for(int i
=1;i
<=n
;i
++) scanf("%d",&a
[i
]);root
[0]=build(1,n
);for(int i
=1;i
<=n
;i
++){if(mp
[a
[i
]]==0) root
[i
]=update(i
,root
[i
-1],1,1,n
);else{int t
=update(mp
[a
[i
]],root
[i
-1],-1,1,n
);root
[i
]=update(i
,t
,1,1,n
);}mp
[a
[i
]]=i
;}mp
.clear();for(int i
=1;i
<=n
;i
++){if(mp
[a
[i
]]==0) cout
<<-a
[i
]<<" ";else cout
<<query(mp
[a
[i
]]+1,root
[i
-1],1,n
)<<" ";mp
[a
[i
]]=i
;}return 0;
}
努力加油a啊,(o)/~
總結
以上是生活随笔為你收集整理的[蓝桥杯][2016年第七届真题]压缩变换(主席树求区间不同数的个数)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。