自体は複雑ではありませんタイトルの意味、パスワード、間違った場所に[I]における総テストシーケンスのmのi回をテストすることです、それは手紙を考えるのは簡単ですが、ソートバケットが、よく見ると、この中のn 2 * 10兆の範囲nは、我々はすべてのストライキの大きい数は+1もその前に技術のいくつかの問題に対処する、見つけるのは難しいことではありません、[I]を使用したいので、完了するためには問題ありませんし、我々は最初のmの配列全体を読んで各端部位置に回数を保存することができる領域は、フォワード計算は後方プラス[I] = [I + 1] + [I]、プラスアルゴリズムの全体的な複雑さを超えるすべての中にのみ位置を格納することができます(N)O次のようにコードであります
#include<bits/stdc++.h>
using namespace std;
int arr[200100],res[30];
int main(){
int t; cin>>t;
while(t--){
int n; cin>>n;
int m; cin>>m;
string s= ""; cin>>s;
for(int i=0; i<n; i++)
res[s[i]-'a']++;
for(int i=0; i<m; i++){
int x; cin>>x;
arr[x]++;
}
for(int i=n; i>=1; i--){
arr[i]+=arr[i+1];
res[s[i-1]-'a']+=arr[i];
}
for(int i=0; i<26; i++)cout<<res[i]<<" ";cout<<endl;
}
return 0;}
半分nlogn練習以下で説明すると、彼はこの位置が間違っているので、私はM-GETその位置、機能よりもlowbound大きいによる最初の位置を見つけ、半分に横断する独自のアルゴリズムに基づいていると出現数が(この間違った後、毎回位置が間違っているだろう)、それは数を増やす必要があるの現在の場所を見つけるには時間がかかるLOGN。
low_bound機能を使用すると、特定の数よりも第1以上の配列にアイテムの過程で数を見つけることができるように、あなたは配列の先頭減算する場所を取得したい場合は、アドレスを返すことに注意してください
コード次のように
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
int n,m;
cin>>n>>m;
string a;
cin>>a;
int p[m+1],mp[600]={0};
for(int i=1;i<=m;i++) cin>>p[i];
sort(p+1,p+m+1);
for(int i=0;i<n;i++)
mp[a[i]]+=m-(lower_bound(p+1,p+m+1,i+1)-p)+1;
for(int i=0;i<n;i++) mp[a[i]]++;
for(char i='a';i<='z';i++){
if(i!='a') cout<<" ";
cout<<mp[i];
}
cout<<endl;
}
return 0;
}