描述
最近小賴的電腦遭遇了一次病毒的“洗禮”,所有的檔案都已損壞。無奈之下,他只好求助於專業的資料恢複公司。工作人員在做完初步的檢測後告訴小賴:只有一次恢複機會且只能恢複一段連續的檔案。而每恢複一個檔案則要花一個單位的錢。
小賴把他電腦裡的檔案分成了M類,他希望每類檔案至少能恢複一個。但是小賴手上只有Money單位 的錢可供支配,所以他希望花的錢盡量的少。
-
輸入
-
第一行有一個整數 T 表示資料的組數,對於每組資料:
第一行有三個整數 N, M, Money分別代表檔案的總數(檔案按儲存順序編號1~N), 檔案的種類數,可供支配的錢數 (1≤N≤1,000,000 ,1≤M≤2000)。
第二行有N個整數,第i個整數代表編號為i的檔案所屬的分類(1~M中的一個)。
-
輸出
-
對於每組測試資料,輸出一行:
如果可以在Money單位的錢數內完成恢複,則輸出兩個整數,表示花錢最少的方案中恢複檔案的起始位置和終止位置,即所要恢複的那段檔案兩端檔案的編號a, b (a <b),如果有多種解決方案,則輸出a最小的那組。
否則,輸出“Poor child!”(不包括引號)。
-
範例輸入
-
212 5 82 5 3 1 3 2 4 1 1 5 4 312 5 42 5 3 1 3 2 4 1 1 5 4 3
-
範例輸出
-
2 7Poor child!
類比題,恢複地區需要包含1到M,同時也要保證最長。
#include <iostream>#include <cstdlib>using namespace std;int main(){int number;cin>>number;int* index;int* zhi;int* result;while(number--){ int n,m,money; cin>>n>>m>>money; index=new int[m+1]; memset(index,0,sizeof(int)*(m+1)); zhi=new int[n+1]; result=new int[n+1]; for(int i=1;i<=n;i++) { cin>>zhi[i]; } int k=0;int p; for(int i=1;i<=n;i++) { if(index[zhi[i]]==0) { k++; p=k; index[zhi[i]]++; if(k==m) { k=i; break; } } else { index[zhi[i]]++; } } int k1 ; for(int i=1;i<=k;i++) { if(index[zhi[i]]==1) { k1=i; break; } else { index[zhi[i]]--; } } result[k]=k1; int mi=k-k1,s=k1,f=k; for(int i=k+1;i<=n;i++) { index[zhi[i]]++; for(int j=result[i-1];j<=i;j++) { if(index[zhi[j]]==1) { result[i]=j; break; } else { index[zhi[j]]--; } } if(i-result[i]<mi) { mi=i-result[i]; s=result[i]; f=i; } } if(p<m) cout<<"Poor child!"<<endl; else if(mi+1>money) cout<<"Poor child!"<<endl; else cout<<s<<" "<<f<<endl; delete [] index; delete [] zhi; delete [] result;}return 0;}