# APCS 2020/10 題解
## ==人力分配==
### <font color="0E81A6">題目</font>
[人力分配](https://zerojudge.tw/ShowProblem?problemid=f312)
### <font color="0E81A6">核心</font>
迴圈、條件判斷
### <font color="0E81A6">思路</font>
```c++=
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,A1,A2,B1,B2,C1,C2;
scanf("%d%d%d%d%d%d%d",&A1,&B1,&C1,&A2,&B2,&C2,&n);
int maxProfit=INT_MIN,profit;
for(int i=0;i<=n;i++)
{
int Y1=A1*i*i+B1*i+C1,Y2=A2*(n-i)*(n-i)+B2*(n-i)+C2;
profit=Y1+Y2;
maxProfit=max(profit,maxProfit);
}
printf("%d\n",maxProfit);
}
```
## ==人口遷移==
### <font color="0E81A6">題目</font>
[人口遷移](https://zerojudge.tw/ShowProblem?problemid=f313)
### <font color="0E81A6">核心</font>
模擬、二維陣列
### <font color="0E81A6">思路</font>
簡易模擬題。
```c++=
#include<bits/stdc++.h>
using namespace std;
#define N 55
int main()
{
int R,C,k,m;
int city[N][N],di[4]={1,0,-1,0},dy[4]={0,1,0,-1},people_num[N][N];
scanf("%d%d%d%d",&R,&C,&k,&m);
memset(city,-1,sizeof(city));
for(int i=1;i<=R;i++)
{
for(int j=1;j<=C;j++) scanf("%d",&city[i][j]),people_num[i][j]=city[i][j]/k;
}
while(m--)
{
for(int i=1;i<=R;i++)
{
for(int j=1;j<=C;j++)
{
if(city[i][j]==-1) continue;
for(int d=0;d<4;d++)
{
if(city[i+di[d]][j+dy[d]]!=-1)
{
city[i+di[d]][j+dy[d]]+=people_num[i][j];
city[i][j]-=people_num[i][j];
}
}
}
}
for(int i=1;i<=R;i++)
{
for(int j=1;j<=C;j++) people_num[i][j]=city[i][j]/k;
}
}
int max_n=0,min_n=INT_MAX;
for(int i=1;i<=R;i++)
{
for(int j=1;j<=C;j++)
{
if(city[i][j]==-1) continue;
max_n=max(city[i][j],max_n);
min_n=min(city[i][j],min_n);
}
}
printf("%d\n%d\n",min_n,max_n);
}
```
## ==勇者修練==
### <font color="0E81A6">題目</font>
[勇者修練](https://zerojudge.tw/ShowProblem?problemid=f314)
### <font color="0E81A6">核心</font>
dp、模擬
### <font color="0E81A6">思路</font>
一列一列考慮,任一點有可能從左或右或上過來,而頭尾只會從上下來。
```c++=
#include<bits/stdc++.h>
using namespace std;
#define N 10005
#define M 55
int A[N];
int dp[M][N]={0};
int m,n;
int main()
{
scanf("%d%d",&m,&n);
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++) scanf("%d",A+j);
int l[N]={0},r[N]={0};
for(int j=1;j<=n;j++)
{
if(j==1) l[j]=dp[i-1][j]+A[j];
else l[j]=max(dp[i-1][j],l[j-1])+A[j];
}
for(int j=n;j>=1;j--)
{
if(j==n) r[j]=dp[i-1][j]+A[j];
else r[j]=max(dp[i-1][j],r[j+1])+A[j];
}
for(int j=1;j<=n;j++)
{
dp[i][j]=max(l[j],r[j]);
}
}
int sum=INT_MIN;
for(int j=1; j<=n; j++)
{
sum=max(dp[m][j],sum);
}
printf("%d\n",sum);
}
```
## ==低地距離==
### <font color="0E81A6">題目</font>
[低地距離](https://zerojudge.tw/ShowProblem?problemid=f315)
### <font color="0E81A6">核心</font>
BIT
### <font color="0E81A6">思路</font>
[大佬思路](https://hackmd.io/@QWERTYPIG/Sy3rQgPb2#%E7%AC%AC%E5%9B%9B%E9%A1%8C-%E4%BD%8E%E5%9C%B0%E8%B7%9D%E9%9B%A2)
```c++=
#include<bits/stdc++.h>
using namespace std;
long long ans=0;
pair<int,int> arr[100010];
struct BIT
{
int sz;
vector<int> dat;
void init(int n)
{
sz=n;
dat.assign(n+1,0);
return;
}
void upd(int id,int x)
{
for(int i=id;i<=sz;i+=i&-i) dat[i]+=x;
return;
}
int sum(int id)
{
int ans=0;
for(int i=id;i>0;i-=i&-i) ans+=dat[i];
return ans;
}
}bit;
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=2*n;i++)
{
int a;
scanf("%d",&a);
if(arr[a].first==0) arr[a].first=i;
else arr[a].second=i;
}
bit.init(2*n);
for(int i=1;i<=n;i++)
{
ans+=bit.sum(arr[i].second-1)-bit.sum(arr[i].first);
bit.upd(arr[i].first,1);
bit.upd(arr[i].second,1);
}
printf("%lld\n",ans);
}
```