---
# System prepended metadata

title: APCS 2022 1月
tags: [Coding]

---

---
tags: Coding
---
# APCS 2022 1月
## P1
https://zerojudge.tw/ShowProblem?problemid=h081
:::spoiler code
```cpp
#include <iostream>
using namespace std;
int main(){
    int n;
    while(cin >> n && n) {
        int d;
        int x =0;
        int price;
        int getting = 0;
        int having;
        cin >> d;
        for (int c=0; c<n;c++){
            cin >> price;
            if(x == 0 || (price <= (x-d) && (!having))){
                x = price;
                having = 1;
            }  
            if(price >= (x+d) && having){
                getting += price-x;
                x=price;
                having = 0;
            }
        }
        cout << getting <<endl;
    }
}
```
:::
## P2
https://zerojudge.tw/ShowProblem?problemid=h082
::: spoiler code
```cpp=
#include <iostream>
#include <vector>
#include <algorithm>
#define int long long
using namespace std;
signed main() {
  int n,m,k;
  while(cin>>n>>m &&n &&m){
    int s[1005],t[100000];
    int lose[1005] = {0};
    vector<int> v,v1,v2;
    for(int i=1;i<=n;i++){
      cin>>s[i];
    }
    for(int i=1;i<=n;i++){
      cin>>t[i];
    }
    for(int i=0;i<n;i++){
      cin>>k;
      v.push_back(k);
    }
    while(v.size()>1){
      for(int i=0;i<v.size()-1;i+=2){
        int fi=v[i],se = v[i+1];
        int a=s[fi],b=t[fi];
        int c=s[se],d=t[se];
        if(a*b>=c*d){
          s[fi] = a+c*d/(2*b);
          t[fi] = b+c*d/(2*a);
          s[se] = c+c/2;
          t[se] = d+d/2;
          lose[se]++;
          if(lose[se]<m)v2.push_back(se);
          v1.push_back(fi);
        }else if(a*b<c*d){
          s[fi] = a+a/2;
          t[fi] = b+b/2;
          s[se] = c+a*b/(2*d);
          t[se] = d+a*b/(2*c);
          lose[fi]++;
          if(lose[fi]<m)v2.push_back(fi);
          v1.push_back(se);
        }
      }
      if((int)v.size()%2 == 1)v1.push_back(v.back());
      v=v1;
      v.insert(v.end(),v2.begin(),v2.end());
      v1.clear();
      v2.clear();
    }
    cout<<v[0]<<endl;
  }
}
```
:::
## P3
https://zerojudge.tw/ShowProblem?problemid=h083
::: spoiler code
```cpp=
#include <bits/stdc++.h>
using namespace std;
int main(){
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  int m;
  while(cin>>m){
    set<string> str;
    string s;
    int ans=0;
    for(int i=0;i<m;i++){
      cin>>s;
      str.insert(s);
    }
    for(auto &a:str){
      int l=a.length();
      if(l<3)continue;
      for(int i=1;i<=l/2;i++){
        if(a.substr(0,i)==a.substr(l-i)){
          if(str.count(a.substr(i,l-2*i)))ans++; 
        }
      }
    }
    cout<<ans<<endl;
  }
  return 0;
}
```
:::
## P4
### 想法一(記憶體不夠)失敗55分
https://zerojudge.tw/ShowProblem?problemid=h084
用離散化儲存每一層樓的相鄰的長度，如果沒有相鄰就砍斷。
![](https://i.imgur.com/M6e4YNp.png)
::: spoiler code
```cpp
#include<bits/stdc++.h>
#define all(a) a.begin(),a.end()
#define pb push_back
using namespace std;
vector<int> dis;
int getID(int a){
    return lower_bound(all(dis),a)-dis.begin()+1;
}
int main () {
    int m,n,heigh=INT_MIN;
    cin>>m>>n;
    vector<int> H(m),W(n),tem(m);
    for(int i=0;i<m;i++){
        cin>>H[i];
        dis.pb(H[i]);
    }
    sort(all(dis));
    dis.erase(unique(all(dis)),dis.end());
    vector<vector<int>>cnt;
    for(int i=0;i<dis.size();i++){
        vector<int>k;
        cnt.push_back(k);
    }
    for(int i=0;i<m;i++){
        heigh=max(heigh,H[i]);
        int id=getID(H[i]);
        int preid=getID(H[i-1]);
        for(int j=0;j<id;j++){
            tem[j]++;
        }
        for(int j=id;j<preid && i!=0;j++){
            cnt[j].pb(tem[j]);
            tem[j]=0;
        }
        if(i==m-1){
            for(int j=0;j<id;j++){
                cnt[j].pb(tem[j]);
            }
        }
    }
    for(int i=0;i<n;i++)cin>>W[i];
    int i;
    for( i=getID(heigh)-1;i>=0;i--){
        int fined=0,k=0;
        for(auto j:cnt[i]){
            if(j>=W[k]){
                k++;
            }
            if(k==n){
                fined=1;
                break;
            }
        }
        if(fined)break;
    }
    cout<<dis[i];
}
```
:::
### 想法二 60分解
針對第一第二子題作答，找指定長度中的最小值，且找每組中最小值得最大解
::: spoiler code
```cpp=
#include<bits/stdc++.h>
#define all(a) a.begin(),a.end()
#define pb push_back
#define int long long
using namespace std;
signed main () {
    int n,k,head=0,ans=LLONG_MIN;
    vector<int> h(200005),w(5005);
    vector<int> minh;
    cin>>n>>k;
    for(int i=0;i<n;i++)cin>>h[i];
    for(int i=0;i<k;i++)cin>>w[i];
    for(int i=0;i<n;i++){
        while(minh.size()>head && h[i]<h[minh.back()])minh.pop_back();
        minh.push_back(i);
        if(minh[head]<=i-w[0])head++;
        if(i>=w[0]-1 && h[minh[head]]>ans)ans=h[minh[head]];
    }
    cout<<ans;
}
```
:::
### 想法三
https://www.youtube.com/watch?v=w0ahlLRFSe0&t=299s
:::spoiler
```cpp=
#include<bits/stdc++.h>
#define all(a) a.begin(),a.end()
using namespace std;

bool test(vector<int>&h , vector<int>&w , int y){
    int hi=0,wi=0;
    while( wi<w.size()){
        int len=0;
        while(y<=h[hi] && len<w[wi] && hi<h.size()){
            len++;
            hi++;
        }
        if(len==w[wi])wi++;
        else if(hi==h.size())return false;
        else if(y>h[hi])hi++;
    }
    return true;
}

signed main(){
    int n,k;
    vector<int>h(2000005),w(5005);
    cin>>n>>k;
    for(int i=0;i<n;i++)cin>>h[i];
    for(int i=0;i<k;i++)cin>>w[i];
    int maxh=*max_element(all(h)),ans=0;
    int jump=maxh;
    while(jump > 0){
        while(ans+jump<=maxh && test(h,w,ans+jump)){
            ans+=jump;
        }
        jump>>=1;
    }
    cout<<ans;
}
```
:::
