HihoCoder - 1483 区间最值
生活随笔
收集整理的這篇文章主要介紹了
HihoCoder - 1483 区间最值
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
給定n個(gè)數(shù)A1...An,小Ho想了解AL..AR中有多少對元素值相同。小Ho把這個(gè)數(shù)目定義為區(qū)間[L,R]的價(jià)值,用v[L,R]表示。
例如1 1 1 2 2這五個(gè)數(shù)所組成的區(qū)間的價(jià)值為4。
現(xiàn)在小Ho想知道在所有的的v[L,R](1 <= L <= R <= n)中,第k小的值是多少。
Input第一行一個(gè)數(shù)T(T<=10),表示數(shù)據(jù)組數(shù)。
對于每一組數(shù)據(jù):
第一行兩個(gè)數(shù)n,k(1<=n<=200,000,1<=k<=n*(n+1)/2)
第二行n個(gè)數(shù)A1…An(1<=Ai<=1,000,000,000)
Output一個(gè)數(shù)表示答案。
Sample Input
2 4 7 1 1 2 3 3 6 100 100 100Sample Output
0 3題意:我們給出n個(gè)數(shù),我們求任意一段區(qū)間,他們相同的數(shù)的次數(shù)就是區(qū)間的值,然后我們按值排序求第k個(gè)區(qū)間的值是多少
思路:開始我用的n2,果斷超時(shí)。。然后我們看到ai的范圍有這么大,我們又要記錄次數(shù),顯然我們可以用map,但是我用map也超時(shí)了,
所以有個(gè)高級的操作,因?yàn)閚的范圍數(shù)組能開的下,只是ai值大而已,所以我們可以離散化,然后我們想一下,怎么求答案呢,如果我們直接求出所有的區(qū)間再排序輸出的話n2復(fù)雜度
所以發(fā)現(xiàn)不行,我們仔細(xì)想想,我們能得知我們區(qū)間長度越小,我們的區(qū)間值肯定更小,我們可以二分去處理,二分的話最小值是0沒有一個(gè)相同,最大的時(shí)候也就是全部的數(shù)都相同,可以推出是n*(n-1)/2
因?yàn)槲覀円笫乔蟮趉個(gè)區(qū)間的值,那么我們就只要去尋找判斷,小于當(dāng)前數(shù)的區(qū)間個(gè)數(shù)有多少個(gè),如果小于這個(gè)數(shù)的區(qū)間比k還大的話,說明我們當(dāng)前的數(shù)肯定比我們要求的小,所以我們向右擴(kuò)展,反之亦然
然后我們想如何去求多少個(gè)區(qū)間比他小呢?
我們可以不用求出所有區(qū)間的值為什么呢,因?yàn)槲覀儏^(qū)間的個(gè)數(shù)和值的大小息息相關(guān)
如果[l.r]是比k小的,那么[l,r-1],[l,r-2]....[l,l]都是小于k的數(shù),這里就用到了我們的尺取法
那么我們就把它變成了一個(gè)nlogn的算法
#include<cstdio> #include<cmath> #include<cstring> #include<map> #include<algorithm> using namespace std; typedef long long ll; ll a[200001]; ll t,n,m,temp[200001]; ll vis[200001]; ll check(ll mid)//尺取求比mid小的區(qū)間個(gè)數(shù) {int i,j;ll sum=0;ll num=0;memset(vis,0,sizeof(vis));for(i=0,j=0;i<n;i++){for(;j<n&&sum+vis[a[j]]<=mid;j++){sum+=vis[a[j]];vis[a[j]]++;}num+=j-i;//尺取思想核心vis[a[i]]--;sum-=vis[a[i]];}return num>=m; } int main() {ll ans;scanf("%lld",&t);while(t--){scanf("%lld%lld",&n,&m);for(int i=0;i<n;i++){scanf("%lld",&a[i]);temp[i]=a[i];}int cnt;sort(temp,temp+n);//離散化cnt = unique(temp,temp+n) - temp;for(int i = 0 ; i < n ; ++i)a[i] = lower_bound(temp,temp+cnt,a[i]) - temp;ll left=0,right=((ll)n*((ll)n-1))/2;while(left<=right){ll mid=(left+right)/2;if(check(mid))//如果小于mid的區(qū)間個(gè)數(shù)比m多的話,說明值還不夠小{ans=mid;right=mid-1;}else{left=mid+1;}}printf("%lld\n",ans);} }
?
轉(zhuǎn)載于:https://www.cnblogs.com/Lis-/p/9393788.html
總結(jié)
以上是生活随笔為你收集整理的HihoCoder - 1483 区间最值的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第十周补做作业
- 下一篇: 使用exp导出导入,需要注意的问题。