# APCS 2022/1 題解
## ==程式交易==
### <font color="0E81A6">題目</font>
[程式交易](https://zerojudge.tw/ShowProblem?problemid=h081)
### <font color="0E81A6">核心</font>
條件判斷
### <font color="0E81A6">思路</font>
不用陣列。
```c++=
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,D;
scanf("%d%d",&n,&D);
int cost,value;
scanf("%d",&cost);
int total=-cost;
bool have=true;
for(int i=1;i<n;i++)
{
scanf("%d",&value);
if(have&&value>=cost+D) total+=value,have=false,cost=value;
if(!have&&value<=cost-D) total-=value,have=true,cost=value;
}
if(have) total+=cost;
printf("%d\n",total);
}
```
## ==贏家預測==
### <font color="0E81A6">題目</font>
[贏家預測](https://zerojudge.tw/ShowProblem?problemid=h082)
### <font color="0E81A6">核心</font>
模擬、vector
### <font color="0E81A6">思路</font>
注意運算時S[i]與T[i]的更動,需先賦予給暫存變數。
vector處理要熟記。
```c++=
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,From,num;
int S[1005],T[1005],Count[1005]={0};
vector<int> order,next_order;
void caculate(int win,int lose,int h)
{
int a,b;
next_order.insert(next_order.begin()+From,win);
a=S[win],b=T[win];
S[win]=S[win]+h/(2*b),T[win]=T[win]+h/(2*a);
S[lose]=S[lose]+S[lose]/2,T[lose]=T[lose]+T[lose]/2;
Count[lose]++;
if(Count[lose]<m) next_order.push_back(lose);
From++;
}
signed main()
{
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",S+i);
for(int i=1;i<=n;i++) scanf("%lld",T+i);
for(int i=0;i<n;i++) scanf("%lld",&num),order.push_back(num);
while(order.size()>1)
{
n=order.size();
int a,b;
From=0;
for(int i=1;i<n;i+=2)
{
int p1=order[i-1],p2=order[i];
int h1=S[p1]*T[p1],h2=S[p2]*T[p2];
if(h1>=h2) caculate(p1,p2,h2);
else caculate(p2,p1,h1);
}
if(n&1) next_order.insert(next_order.begin()+From,order[n-1]);
order=next_order;
next_order.clear();
}
printf("%lld\n",order[0]);
}
```
## ==數位占卜==
### <font color="0E81A6">題目</font>
[數位占卜](https://zerojudge.tw/ShowProblem?problemid=h083)
### <font color="0E81A6">核心</font>
string、枚舉、set
### <font color="0E81A6">思路</font>
枚舉每一個字串,將頭尾分別長度由小到大拆分,若頭尾相同,則去set裡找中間子字串。
由於查找子字串長度會是較短方,故答案不會重複計算。
```c++=
#include<bits/stdc++.h>
using namespace std;
set<string> S;
vector<string> V;
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
int m;
cin>>m;
for(int i=0;i<m;i++)
{
string str;
cin>>str;
S.insert(str);
V.push_back(str);
}
int ans=0;
for(auto s:V)
{
for(int len=1; len<=s.size()/2; len++)
{
string head=s.substr(0,len);
string tail=s.substr(s.size()-len,len);
if(head==tail)
{
string want=s.substr(len,s.size()-2*len);
ans+=S.count(want);
}
}
}
cout<<ans<<endl;
}
```
## ==牆上海報==
### <font color="0E81A6">題目</font>
[牆上海報](https://zerojudge.tw/ShowProblem?problemid=h084)
### <font color="0E81A6">核心</font>
二分搜、貪婪
### <font color="0E81A6">思路</font>
這題我以為不用照順序,害我卡個半死。
```c++=
#include<bits/stdc++.h>
using namespace std;
#define N 200005
int n,k,f[N],poster[5000];
bool post(int high)
{
vector<int> V;
int length=0;
for(int i=0;i<n;i++)
{
if(f[i]>=high) length++;
else
{
if(length!=0) V.push_back(length),length=0;
}
}
if(length!=0) V.push_back(length);
int cnt=0;
for(int i=k-1;i>=0&&V.size();i--)
{
if(V.back()>=poster[i])
{
cnt++;
V.back()-=poster[i];
}
else
{
while(V.back()<poster[i]&&V.size()) V.pop_back();
i++;
}
}
return cnt==k;
}
int findh()
{
int l=1,r=1e9+1,mid;
while(l<r)
{
mid=(l+r)/2;
bool can=post(mid);
if(can) l=mid+1;
else r=mid;
}
return l-1;
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++) scanf("%d",f+i);
for(int i=0;i<k;i++) scanf("%d",poster+i);
int maxh=findh();
printf("%d\n",maxh);
}
```