PAT甲级刷题记录(更新中~只记录有思考价值的题)

此博客用于记录PTA平台上 PAT (Advanced Level) Practice题目集 中有思考价值的题。

有意向刷PAT甲级的小伙伴,可以参考,少刷水题!


1007 Maximum Subsequence Sum

DP O(n)

1014 Waiting in Line

1017 Queueing at Bank

1016 Phone Bills

分类讨论

1033 To Fill or Not to Fill

贪心

1038 Recover the Smallest Number

排序

1040 Longest Symmetric String

Manercher算法 O(n)

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f;

int manercher(string t){
    string s="$#";
    for(int i=0;i<t.size();i++){
        s+=t[i];s+='#';
    }
    s+='^';
    vector<int>p(s.size());
    int mr=0,mid;
    for(int i=1;i<s.size();i++){
        if(i<mr)p[i]=min(p[mid*2-i],mr-i+1);
        else p[i]=1;
        while(s[i-p[i]]==s[i+p[i]])p[i]++;//最多执行n次
        if(i+p[i]>mr){
            mid=i;
            mr=i+p[i]-1;
        }
    }
    int ans=0;
    for(int i=0;i<p.size();i++){
        ans=max(p[i]-1,ans);
    }
    return ans;
}

void solve(){
    string s;getline(cin,s);
    cout<<manercher(s)<<endl;
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

1044 Shopping in Mars

双指针+前缀和 O(n)

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
#define x first
#define y second
typedef pair<int,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f;
void solve(){
    int n,w;cin>>n>>w;
    vector<int>a(n+1);
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    vector<int>s(n+1);
    for(int i=1;i<=n;i++){
        s[i]=s[i-1]+a[i];
    }
    int l=1,r=1;
    vector<PII>ans;
    int mx=1e9;
    while(r<=n){
        if(s[r]-s[l-1]==w){
            ans.push_back({l,r});
            if(r<=n)l++,r++;
        }else{
            while(l<=r&&s[r]-s[l-1]>w){mx=min(mx,s[r]-s[l-1]);l++;}
            if(s[r]-s[l-1]==w)ans.push_back({l,r});
            r++;
        }
    }
    if(ans.size())
        for(auto i:ans){cout<<i.x<<'-'<<i.y<<endl;}
    else{
        w=mx;
        l=1,r=1;
        while(r<=n){
        if(s[r]-s[l-1]==w){
            ans.push_back({l,r});
            if(r<=n)l++,r++;
        }else{
            while(l<=r&&s[r]-s[l-1]>w)l++;
                if(s[r]-s[l-1]==w)ans.push_back({l,r});
                r++;
            }
        }
        for(auto i:ans){cout<<i.x<<'-'<<i.y<<endl;}
    }
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

1048 Find Coins

此题由1044改编,故放在一起

法一:排序+双指针 O(nlongn)

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f;
void solve(){
    int n,m;cin>>n>>m;
    vector<int>a(n);
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    sort(all(a));
    int l=0,r=n-1;
    while(l<r){
        if(a[l]+a[r]>m){
            r--;
        }else if(a[l]+a[r]<m){
            l++;
        }else{
            cout<<a[l]<<' '<<a[r]<<endl;
            return;
        }
    }
    cout<<"No Solution\n";
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

法二:哈希   O(n) 或者 O(m) 都可以实现

所以如果题目的N值很大的话,只能使用哈希法

1045 Favorite Color Stripe

DP O(n*m)

dp[i][j] 表示使用前i个颜色,且最右面的颜色为 第j个最喜欢的颜色 的最大长度

状态转移:dp[i][j] = max{ dp[i-1] [ 1~j ] } + 1

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
const int N=10001;
const int mod=998244353;
const int INF=0x3f3f3f3f;
int dp[N][201];
void solve(){
    int tot;cin>>tot;
    int n;cin>>n;
    vector<int>v(n+1);
    for(int i=1;i<=n;i++)cin>>v[i];
    int m;cin>>m;
    vector<int>mx(n+1);
    int ans=0;
    for(int i=1;i<=m;i++){
        int a;cin>>a;
        int t=0;
        for(int j=1;j<=n;j++){
            t=max(t,dp[i-1][j]);
            dp[i][j]=dp[i-1][j];
            if(a==v[j])dp[i][j]=t+1;
            ans=max(ans,dp[i][j]);
        }
    }
    cout<<ans<<endl;
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

滚动数组优化:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
const int N=10001;
const int mod=998244353;
const int INF=0x3f3f3f3f;
int dp[201];
void solve(){
    int tot;cin>>tot;
    int n;cin>>n;
    vector<int>v(n+1);
    for(int i=1;i<=n;i++)cin>>v[i];
    int m;cin>>m;
    vector<int>mx(n+1);
    int ans=0;
    for(int i=1;i<=m;i++){
        int a;cin>>a;
        int t=0;
        for(int j=1;j<=n;j++){
            t=max(t,mx[j]);
            if(a==v[j])dp[j]=t+1;
        }
        for(int j=1;j<=n;j++){
            mx[j]=max(mx[j],dp[j]);
            ans=max(ans,dp[j]);
        }
    }
    cout<<ans<<endl;
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

1049 Counting Ones

数位dp(记忆化搜索)

时间复杂度=状态数*转移数=O(10*2*2*10)*10=O(4000)

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f;
vector<int>nums;
unordered_map<int,int>book;
int hs(int i,int is_limit,int is_num,int cnt){
    return cnt*10000+i*100+is_limit*10+is_num;
}
int ans;
string s;
int dfs(int i,int is_limit,int is_num,int cnt){
    if(i==-1){
        return cnt;
    }
    if(book.count(hs(i,is_limit,is_num,cnt)))return book[hs(i,is_limit,is_num,cnt)];
    int res=0;
    if(!is_num)res+=dfs(i-1,false,false,cnt);
    int up=9;//上界
    if(is_limit)up=nums[i];
    for(int j=1-is_num;j<=up;j++){
        if(j==1)res+=dfs(i-1,is_limit&&j==up,true,cnt+1);
        else res+=dfs(i-1,is_limit&&j==up,true,cnt);
    }
    book[hs(i,is_limit,is_num,cnt)]=res;
    return res;
}
void solve(){
    int n;cin>>n;
    while(n)nums.push_back(n%10),n/=10;//把n的每一位扣出来
    cout<<dfs(nums.size()-1,1,0,0)<<endl;
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

1055 The World's Richest

此题需要严格分析时间复杂度

超时版本1  K*N*logN=1.7e8

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
#define x first
#define y second
typedef pair<string,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f;
struct Node{
    string name;
    int age,wea;
    bool operator<(const Node &n)const{
        if(wea!=n.wea){
            return wea>n.wea;
        }
        if(age!=n.age){
            return age<n.age;
        }
        return name<n.name;
    }
};
void solve(){
    int n,m;cin>>n>>m;
    vector<int>v;
    set<int>st{300};
    vector<PII>age[300];
    for(int i=0;i<n;i++){
        string a;int b,c;cin>>a>>b>>c;
        age[b].push_back({a,c});
        st.insert(b);
    }
    for(int i=1;i<=m;i++){
        cout<<"Case #"<<i<<":\n";
        int mx,l,r;cin>>mx>>l>>r;
        vector<Node>ans;
        auto a=st.lower_bound(l);
        for(;*a!=300;a++){
            if(*a>r)break;
            for(auto j:age[*a]){
                ans.push_back({j.x,*a,j.y});
            }
        }
        sort(all(ans));
        for(int j=0;j<ans.size()&&j<mx;j++){
            cout<<ans[j].name<<' '<<ans[j].age<<' '<<ans[j].wea<<endl;
        }
        if(!ans.size()||!mx){
            cout<<"None\n";
        }
    }
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

超时版本2  K*200*100*log100=1.4e8

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
#define x first
#define y second
typedef pair<string,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f;
struct Node{
    string name;
    int age,wea;
    bool operator<(const Node &n)const{
        if(wea!=n.wea){
            return wea>n.wea;
        }
        if(age!=n.age){
            return age<n.age;
        }
        return name<n.name;
    }
};
void solve(){
    int n,m;cin>>n>>m;
    vector<int>v;
    set<int>st{300};
    vector<PII>age[300];
    for(int i=0;i<n;i++){
        string a;int b,c;cin>>a>>b>>c;
        age[b].push_back({a,c});
        st.insert(b);
    }
    for(int i=1;i<=m;i++){
        cout<<"Case #"<<i<<":\n";
        int mx,l,r;cin>>mx>>l>>r;
        vector<Node>ans;
        auto a=st.lower_bound(l);
        for(;*a!=300;a++){
            if(*a>r)break;
            for(auto j:age[*a]){
                if(ans.size()==mx+1){sort(all(ans));ans.pop_back();}
                ans.push_back({j.x,*a,j.y});
            }
        }
        sort(all(ans));
        for(int j=0;j<ans.size()&&j<mx;j++){
            cout<<ans[j].name<<' '<<ans[j].age<<' '<<ans[j].wea<<endl;
        }
        if(!ans.size()||!mx){
            cout<<"None\n";
        }
    }
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

正解: K*N = 1e7

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
#define x first
#define y second
typedef pair<string,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f;
struct Node{
    string name;
    int age,wea;
    bool operator<(const Node &n)const{
        if(wea!=n.wea){
            return wea>n.wea;
        }
        if(age!=n.age){
            return age<n.age;
        }
        return name<n.name;
    }
};
void solve(){
    int n,m;cin>>n>>m;
    vector<Node>tmp;
    vector<Node>v;
    int book[300]={};
    for(int i=0;i<n;i++){
        string a;int b,c;cin>>a>>b>>c;
        tmp.push_back({a,b,c});
    }
    sort(all(tmp));
    for(auto [a,b,c]:tmp){
        if(book[b]<=100){
            v.push_back({a,b,c});
            book[b]++;
        }
    }
    for(int i=1;i<=m;i++){
        cout<<"Case #"<<i<<":\n";
        int mx,l,r;cin>>mx>>l>>r;
        int cnt=0;
        for(int j=0;j<v.size();j++){
            if(v[j].age>=l&&v[j].age<=r){
                cout<<v[j].name<<' '<<v[j].age<<' '<<v[j].wea<<endl;
                cnt++;
            }
            if(cnt==mx)break;
        }
        if(!cnt)cout<<"None\n";
    }
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

1056 Mice and Rice

题意抽象,用队列模拟,没有想到更好的方法

时间复杂度约为O(2n)

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f;
void solve(){
    int n,m;cin>>n>>m;
    vector<int>v(n);
    for(int i=0;i<n;i++){
        int a;cin>>a;
        v[i]=a;
    }
    queue<int>q1;
    queue<int>q2;
    vector<int>ans(n);
    for(int i=0;i<n;i++){int a;cin>>a;q2.push(a);ans[i]=1;}
    while(q2.size()!=1){
        while(q2.size()){q1.push(q2.front());q2.pop();}
        int rank=q1.size()/m+(bool)(q1.size()%m);
        while(q1.size()){
            int lst=-1;
            for(int i=0;q1.size()&&i<m;i++){
                auto t=q1.front();
                // cout<<t<<' ';
                if(lst==-1){ans[t]=rank+1;lst=t;}
                else if(v[t]>v[lst]){ans[lst]=rank+1;lst=t;}
                else if(v[t]<v[lst]){ans[t]=rank+1;}
                q1.pop();
            }
            ans[lst]=rank;
            q2.push(lst);
        }
    }
    int first=1;
    for(int i=0;i<n;i++){
        if(first){cout<<ans[i];first=0;}
        else cout<<' '<<ans[i];
    }
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

1057 Stack

增删查至少logN复杂度,所以不能用vector

法一:两个multiset维护中位数(细节太多不好调试)

O(nlogn)

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f;
stack<int>st;
multiset<int>l,r;
void pop(int a){
    if(l.size()>r.size()){
        if(l.find(a)!=l.end()){
            l.erase(l.find(a));
        }else{
            r.erase(r.find(a));
            r.insert(*(--l.end()));
            l.erase((--l.end()));
        }
    }else if(l.size()==r.size()){
        if(r.find(a)!=r.end()){
            r.erase(r.find(a));
        }else{
            l.erase(l.find(a));
            l.insert(*(r.begin()));
            r.erase(r.begin());
        }
    }
}
void insert(int a){
    if(!l.size()){l.insert(a);return;}
    int mid=*(--l.end());
    if(l.size()>r.size()){
        if(a>=mid)r.insert(a);
        else if(a<mid){
            r.insert(mid);
            l.erase((--l.end()));
            l.insert(a);
        }
    }else if(l.size()==r.size()){
        if(a<=*r.begin())l.insert(a);
        else{
            l.insert(*r.begin());
            r.erase(r.begin());
            r.insert(a);
        }
    }
}
void solve(){
    string op;cin>>op;
    if(op=="Push"){
        int a;cin>>a;
        st.push(a);
        insert(a);
    }else if(op=="Pop"){
        if(!st.size()){
            cout<<"Invalid\n";
            return;
        }
        int a=st.top();
        cout<<a<<endl;
        st.pop();
        pop(a);
    }else{
        if(!st.size()){
            cout<<"Invalid\n";
            return;
        }
        cout<<*(--l.end())<<endl;
    }
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    cin>>_;
    while(_--)solve();
    return 0;
}

法二:树状数组+二分(求第k小的数 经典做法)

O(nlognlogn)

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) (x&-x)
const int N=100010;
int tr[N];
int mx;
void add(int t,int val){
    for(int i=t;i<=mx;i+=lowbit(i)){
        tr[i]+=val;
    }
}
int query(int t){
    int ret=0;
    for(int i=t;i>=1;i-=lowbit(i)){
        ret+=tr[i];
    }
    return ret;
}
int main(){
    int n;cin>>n;mx=N;//mx=N是按数的大小范围,而不是个数
    stack<int>st;
    while(n--){
        string s;cin>>s;
        if(s=="Push"){
            int a;cin>>a;
            st.push(a);
            add(a,1);
        }else if(s=="Pop"){
            if(!st.size()){
                cout<<"Invalid\n";
                continue;
            }
            int a=st.top();
            st.pop();
            cout<<a<<endl;
            add(a,-1);
        }else{
            if(!st.size()){
                cout<<"Invalid\n";
                continue;
            }
            int l=0,r=mx;
            int k=(st.size()+1)/2;
            while(l+1!=r){
                int mid=l+r>>1;
                if(query(mid)>=k)r=mid;
                else l=mid;
            }
            cout<<r<<endl;
        }
    }
}

1060 Are They Equal

分类讨论大模拟

有个很恶心的测试点:输入的整数也可能有前导零,所以要进行处理

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"NO"<<endl
#define yes cout<<"YES"<<endl
#define endl '\n'
#define x first
#define y second
typedef pair<string,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f;
int n;
PII check(string s){
    int cnt=s.size();
    if(s=="0")cnt=0;
    string t=s;
    if(s.find('.')!=-1){
        cnt=s.find('.');
        t=s.substr(0,s.find('.'))+s.substr(s.find('.')+1);
        if(t[0]=='0'){
            cnt=0;
            for(int i=1;i<t.size();i++){
                if(t[i]!='0'){
                    t=t.substr(i);
                    cnt=1-i;
                    break;
                }
            }
        }
    }
    if(t.size()<n){
        t+=string(n-t.size(),'0');
    }else{
        t=t.substr(0,n);
    }
    return {t,cnt};
}
void solve(){
    string a,b;cin>>n>>a>>b;
    int i=0;
    while(i+1<a.size()&&a[i]=='0'&&a[i+1]!='.')i++;a=a.substr(i);
    i=0;
    while(i+1<b.size()&&b[i]=='0'&&b[i+1]!='.')i++;b=b.substr(i);
    PII t1=check(a);
    PII t2=check(b);
    if(t1==t2){
        cout<<"YES 0."<<t1.x<<"*10^"<<t1.y<<endl;
    }else{
        cout<<"NO 0."<<t1.x<<"*10^"<<t1.y<<" 0."<<t2.x<<"*10^"<<t2.y<<endl;
    }
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

1063 Set Similarity

哈希(与1048的法二一样)

此题的测试点数据有点弱,使用set的时间复杂度O(M*K*logM) 也能过

正解:使用哈希表 O(M*K)=2e7

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f;
void solve(){
    int n;cin>>n;
    unordered_map<int,int>mp[n+1];
    for(int i=1;i<=n;i++){
        int m;cin>>m;
        for(int j=0;j<m;j++){
            int a;cin>>a;
            mp[i][a]++;
        }
    }
    int q;cin>>q;
    while(q--){
        int a,b;cin>>a>>b;
        int nc=0,nt=mp[b].size();
        for(auto [i,j]:mp[a]){
            if(mp[b].count(i)){
                nc++;
            }else nt++;
        }
        cout<<fixed<<setprecision(1)<<(1.0*nc/nt*100)<<'%'<<endl;
    }
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

1064 Complete Binary Search Tree

O(nlogn):

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
#define x first
#define y second
typedef pair<int,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f;
vector<int>v;
int getroot(int l,int r){
    if(l>r)return -1;
    int cnt=0;
    int t=2,sum=1;
    int n=r-l+1;
    while(sum+t<=n){
        cnt++;
        sum+=t;
        t*=2;
    }
    int left=min(n-sum,1ll<<cnt);
    int root=sum/2+left+l;
    return root;
}
int first=1;
void level(int l,int r){
    queue<PII>q;
    q.push({l,r});
    while(q.size()){
        auto t=q.front();
        q.pop();
        int root=getroot(t.x,t.y);
        if(root!=-1){
            if(first){cout<<v[root];first=0;}
            else cout<<' '<<v[root];
        }
        if(t.x<=root-1){
            q.push({t.x,root-1});
        }
        if(root+1<=t.y){
            q.push({root+1,t.y});
        }
    }
}
void solve(){
    int n;cin>>n;
    for(int i=0;i<n;i++){
        int a;cin>>a;
        v.push_back(a);
    }
    sort(all(v));
    level(0,n-1);
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

正解O(n) 利用性质:二叉搜索树的中序遍历是递增序列

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f;
int in[N];
int tr[N],idx;
int n;
void build(int t){
    if(t>=n)return;
    build(t*2+1);
    tr[t]=in[idx++];
    build(t*2+2);
}
void solve(){
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>in[i];
    }
    sort(in,in+n);
    build(0);
    cout<<tr[0];
    for(int i=1;i<n;i++)cout<<' '<<tr[i];
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

1066 Root of AVL Tree

平衡二叉树模板题

1123 Is It a Complete AVL Tree

判断AVL树

1067 Sort with Swap(0, i)

思维题

O(n)

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f;
void solve(){
    int n;cin>>n;
    vector<int>nx(n);
    int idx=0;
    for(int i=0;i<n;i++){
        int a;cin>>a;
        nx[a]=i;
    }
    int cnt=0;
    for(int i=0;i<n;i++){
        while(nx[0]!=0){
            swap(nx[0],nx[nx[0]]);
            cnt++;
        }
        if(nx[i]!=i){
            swap(nx[0],nx[i]);
            cnt++;
        }
    }
    cout<<cnt<<endl;
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

1078 Hashing

解决哈希冲突:二次探测法

线性探测:1 2 3.... 从冲突位置不断往后找下一个可以存放的下标

二次探测:1 4 9 ... 从冲突位置不断往后找i的二次方的下标

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f3f3f3f3f;
vector<int>prime;
int book[N];
int cnt;
void get_prime(int n=N-1){
    for(int i=2;i<=n;i++){//枚举k
        if(!book[i])prime.push_back(i);
        for(int j=0;prime[j]*i<=n;j++){//p*k<=n
            book[prime[j]*i]=1;
            if(i%prime[j]==0)break;//k不包含比p小的质因子
        }
    }
}
void solve(){
    get_prime();
    int t,n;cin>>t>>n;
    t=*lower_bound(all(prime),t);
    vector<int>book(t);
    int first=1;

    auto check=[&](int a){
        if(book[a%t]){
            for(int i=0;i<t;i++){
                if(!book[(a+i*i)%t]){
                    book[(a+i*i)%t]=1;
                    return (a+i*i)%t;
                }
            }
            return (int)-1;
        }else{
            book[a%t]=1;
            return a%t;
        }
    };

    for(int i=0;i<n;i++){
        int a;cin>>a;
        if(first){
            int p=check(a);
            if(p==-1) cout<<"-";
            else cout<<p;
            first=0;
        }else{
            int p=check(a);
            if(p==-1) cout<<" -";
            else cout<<' '<<p;
        }
    }
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

1080 Graduate Admission

O(n*k+mn)

思路巧妙

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f3f3f3f3f;
struct Node{
    int ge,gi;
    int id;
    bool operator<(const Node& n)const{
        if(ge+gi!=n.ge+n.gi){
            return ge+gi>n.ge+n.gi;
        }
        if(ge!=n.ge)return ge>n.ge;
        return id<n.id;
    }
};
void solve(){
    int n,m,k;cin>>n>>m>>k;
    vector<int>quota(m);
    for(int i=0;i<m;i++){
        cin>>quota[i];
    }
    vector<Node>rank;
    vector<int>prefer[n];
    vector<Node>stu(n);
    for(int i=0;i<n;i++){
        int a,b;cin>>a>>b;
        for(int j=0;j<k;j++){
            int x;cin>>x;
            prefer[i].push_back(x);
        }
        stu[i]={a,b,i};
        rank.push_back({a,b,i});
    }
    sort(all(rank));
    vector<int>ans[m];
    for(int i=0;i<n;i++){
        int t=rank[i].id;
        for(auto j:prefer[t]){
            if(ans[j].size()<quota[j]){
                ans[j].push_back(t);
                break;
            }else if(stu[ans[j].back()].ge+stu[ans[j].back()].gi==stu[t].ge+stu[t].gi&&stu[ans[j].back()].ge==stu[t].ge){
                ans[j].push_back(t);
                break;
            }
        }
    }

    for(int i=0;i<m;i++){
        sort(all(ans[i]));
        if(ans[i].size())cout<<ans[i][0];
        for(int j=1;j<ans[i].size();j++){
            cout<<' '<<ans[i][j];
        }
        cout<<endl;
    }

}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

1085 Perfect Sequence

常规解法二分:O(nlogn)

最优解O(n)

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f3f3f3f3f;
void solve(){
    int n,p;cin>>n>>p;
    vector<int>v(n);
    for(int i=0;i<n;i++){
        cin>>v[i];
    }
    sort(all(v));
    int j=0;
    int ans=0;
    for(int i=0;i<n;i++){
        while(j<n&&v[i]*p>=v[j])j++;
        ans=max(ans,j-i);
    }
    cout<<ans<<endl;
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

1086 Tree Traversals Again

pop的顺序:左根右

push的顺序:根左右

转化成已知前中序求后序

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f3f3f3f3f;
vector<int>in;
vector<int>pre;
vector<int>post;
void getpost(int root,int l,int r){
    if(l>r)return;
    int i=l;
    while(i<=r&&in[i]!=pre[root])i++;
    getpost(root+1,l,i-1);
    getpost(root+i-l+1,i+1,r);
    post.push_back(pre[root]);
}
void solve(){
    int n;cin>>n;
    stack<int>st;
    for(int i=0;i<2*n;i++){
        string op;cin>>op;
        if(op=="Push"){
            int x;cin>>x;
            st.push(x);
            pre.push_back(x);
        }else{
            in.push_back(st.top());
            st.pop();
        }
    }
    getpost(0,0,n-1);
    cout<<post[0];
    for(int i=1;i<post.size();i++){
        cout<<' '<<post[i];
    }
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

1089 Insert or Merge

稍微不一样的归并排序

当n不是特别大的情况下,这里的归并排序可用sort代替,肯定是比归并排序慢一些的,因为暴力sort并没有用到区间部分有序这个信息

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f3f3f3f3f;
void solve(){
    int n;cin>>n;
    vector<int>v(n);
    for(int i=0;i<n;i++){
        cin>>v[i];
    }
    vector<int>final(n);
    for(int i=0;i<n;i++){
        cin>>final[i];
    }

    auto check=[&](vector<int> &tmp){
        for(int i=0;i<n;i++){
            if(tmp[i]!=final[i])return 0;
        }
        return 1;
    };

    vector<int>tmp=v;
    for(int i=2;i<n;i++){
        sort(tmp.begin(),tmp.begin()+i);
        if(check(tmp)){
            sort(tmp.begin(),tmp.begin()+i+1);
            cout<<"Insertion Sort\n";
            cout<<tmp[0];
            for(int i=1;i<n;i++){
                cout<<' '<<tmp[i];
            }cout<<endl;
            return;
        };
    }

    function<void(int,int)> merge=[&](int l,int r){
        if(l>=r)return;
        int mid=l+r>>1;
        merge(l,mid);
        merge(mid+1,r);
        int p1=l,p2=mid+1;
        int idx=0;
        while(p1<=mid&&p2<=r){
            if(v[p1]<=v[p2])tmp[idx++]=v[p1++];
            else if(p2<=r)tmp[idx++]=v[p2++];
        }
        while(p1<=mid)tmp[idx++]=v[p1++];
        while(p2<=r)tmp[idx++]=v[p2++];

        idx=0;
        for(int i=l;i<=r;i++){
            v[i]=tmp[idx++];
        }
    };

    for(int i=2;i<=2*n;i*=2){
        for(int j=0;j<n;j+=i){
            merge(j,min(n-1,j+i-1));
        }
        if(check(v)){
            i*=2;
            for(int j=0;j<n;j+=i){
                merge(j,min(n-1,j+i-1));
            }
            cout<<"Merge Sort\n";
            cout<<v[0];
            for(int i=1;i<n;i++){
                cout<<' '<<v[i];
            }cout<<endl;
            return;
        }
    }
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

1098 Insertion or Heap Sort

此题的堆排序不需要先构建大顶堆,因为如果是堆排序的话一定是构建好了大顶堆

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f3f3f3f3f;
void solve(){
    int n;cin>>n;
    vector<int>v(n);
    vector<int>final(n);
    for(int i=0;i<n;i++){
        cin>>v[i];
    }
    for(int i=0;i<n;i++){
        cin>>final[i];
    }
    for(int i=2;i<n;i++){
        sort(v.begin(),v.begin()+i);
        if(v==final){
            sort(v.begin(),v.begin()+i+1);
            cout<<"Insertion Sort\n";
            cout<<v[0];
            for(int i=1;i<v.size();i++){
                cout<<' '<<v[i];
            }
            return;
        }
    }
    auto adjust_down=[&](int l,int r){
        int t=l;
        int j=t*2+1;
        while(j<=r){
            if(j+1<=r&&final[j]<final[j+1])j++;
            if(final[t]>=final[j])return;
            swap(final[t],final[j]);
            t=j;
            j=2*t+1;
        }
    };
    int i=1;
    while(i<n&&final[0]>final[i])i++;i--;
    swap(final[0],final[i]);
    adjust_down(0,i-1);
    cout<<"Heap Sort\n";
    cout<<final[0];
    for(int i=1;i<final.size();i++){
        cout<<' '<<final[i];
    }
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

1091 Acute Stroke

题意抽象

三维BFS

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f3f3f3f3f;
int dir[6][3]={1,0,0,0,1,0,0,0,1,-1,0,0,0,-1,0,0,0,-1};
void solve(){
    int m,n,l,t;cin>>m>>n>>l>>t;
    vector<vector<vector<int>>> g(m,vector<vector<int>>(n,vector<int>(l)));
    vector<vector<vector<int>>> book(m,vector<vector<int>>(n,vector<int>(l)));
    for(int i=0;i<l;i++){
        for(int j=0;j<m;j++){
            for(int k=0;k<n;k++){
                cin>>g[j][k][i];
            }
        }
    }

    auto bfs=[&](int a,int b,int c){
        queue<array<int,3>>q;
        q.push({a,b,c});
        int cnt=1;
        book[a][b][c]=1;
        while(q.size()){
            auto t=q.front();
            q.pop();
            for(int i=0;i<6;i++){
                int tx=t[0]+dir[i][0],ty=t[1]+dir[i][1],tz=t[2]+dir[i][2];
                if(tx<0||ty<0||tz<0||tx>=m||ty>=n||tz>=l||book[tx][ty][tz]||!g[tx][ty][tz])continue;
                book[tx][ty][tz]=1;
                cnt++;
                q.push({tx,ty,tz});
            }
        }
        if(cnt>=t)return cnt;
        return 0ll;
    };

    int ans=0;
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++){
            for(int k=0;k<l;k++){
                if(!book[i][j][k]&&g[i][j][k]){
                    ans+=bfs(i,j,k);
                }
            }
        }
    }
    cout<<ans<<endl;
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

1103 Integer Factorization

DFS

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define all(x) x.begin(),x.end()
#define no cout<<"No"<<endl
#define yes cout<<"Yes"<<endl
#define endl '\n'
// #define x first
// #define y second
typedef pair<int,int> PII;
// const int N=200010;
const int mod=998244353;
const int INF=0x3f3f3f3f3f3f3f3f;
int N,K,P;
vector<int>ans;
vector<int>tmp;
int s=0;
void dfs(int t,int cnt,int now,int sum){
    // cout<<t<<' '<<cnt<<' '<<now<<' '<<sum<<endl;
    if(now+K-cnt>N)return;
    if(cnt==K){
        if(now==N){
            if(sum>s){
                s=sum;
                ans=tmp;
            }
        }
        return;
    }
    for(int i=t;i>=1;i--){
        tmp.push_back(i);
        dfs(i,cnt+1,now+pow(i,P),sum+i);
        tmp.pop_back();
    }
}
void solve(){
    cin>>N>>K>>P;
    dfs(pow(N-(K-1),1.0/P),0,0,0);
    if(!ans.size())cout<<"Impossible\n";
    else{
        cout<<N<<" = "<<ans[0]<<'^'<<P;
        for(int i=1;i<ans.size();i++){
            cout<<" + "<<ans[i]<<'^'<<P;
        }
    }
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    int _=1;
    while(_--)solve();
    return 0;
}

1122 Hamiltonian Cycle

哈密顿路径:连通所有点

1126 Eulerian Path

欧拉路径:连通所有边

1130 Infix Expression

对于中缀表达式树的某个节点,不会出现其有左子树而没有右子树的情况,因为如果这个节点是单目运算符,由于是中序遍历左根右,那么应该就是这个节点有右子树而没有左子树

而且只对于右子树需要加上括号来表明优先级

1131 Subway Map

图论含环,由于边权为1所以可以直接dfs,否则就需要Dijkstra+dfs

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值