---
# System prepended metadata

title: APCS 2021/11 題解

---

# APCS 2021/11題解
## ==修補圍籬==
### <font color="0E81A6">題目</font>
[修補圍籬](https://zerojudge.tw/ShowProblem?problemid=g595)
### <font color="0E81A6">核心</font>
陣列、條件判斷
### <font color="0E81A6">思路</font>
陣列頭尾建一個超高圍籬。
```c++=
#include<bits/stdc++.h>
using namespace std;
#define oo 1000
int main()
{
    int n,fence[102];
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",fence+i);
    fence[0]=oo,fence[n+1]=oo;
    int cost=0;
    for(int i=1;i<=n;i++)
    {
        if(fence[i]==0) cost+=min(fence[i-1],fence[i+1]);
    }
    printf("%d\n",cost);
}
```
## ==動線安排==
### <font color="0E81A6">題目</font>
[動線安排](https://zerojudge.tw/ShowProblem?problemid=g596)
### <font color="0E81A6">核心</font>
搞人、模擬
### <font color="0E81A6">思路</font>
純屬搞人心態。
```c++=
#include<bits/stdc++.h>
using namespace std;
int m,n,h,r,c,t,arr[100][100]={},mx=0;
bool findNeighbor(int x,int y,int d) //up 0 down 1 left 2 right 3
{
    if(d==0)
    {
        for(int i=x-1;i>=0;i--) if(arr[i][y]==-1) return 1;
        return 0;
    }
    else if(d==1)
    {
        for(int i=x+1;i<m;i++) if(arr[i][y]==-1) return 1;
        return 0;
    }
    else if(d==2)
    {
        for(int i=y-1;i>=0;i--) if(arr[x][i]==-1) return 1;
        return 0;
    }
    else
    {
        for(int i=y+1;i<n;i++) if(arr[x][i]==-1) return 1;
        return 0;
    }
}
void rmv(int x,int y,int d)
{
    if(d==0)
    {
        for(int i=x-1;i>=0;i--)
        {
            if(arr[i][y]==-1) return;
            else if(arr[i][y]>0) arr[i][y]--;
        }
    }
    else if(d==1)
    {
        for(int i=x+1;i<m;i++)
        {
            if(arr[i][y]==-1) return;
            else if(arr[i][y]>0) arr[i][y]--;
        }
    }
    else if(d==2)
    {
        for(int i=y-1;i>=0;i--)
        {
            if(arr[x][i]==-1) return;
            else if(arr[x][i]>0) arr[x][i]--;
        }
    }
    else
    {
        for(int i=y+1;i<n;i++)
        {
            if(arr[x][i]==-1) return;
            else if(arr[x][i]>0) arr[x][i]--;
        }
    }
}
void cutWire(int x,int y,int d)
{
    if(d==0)
    {
        for(int i=x-1;i>=0;i--)
        {
            if(arr[i][y]==0||arr[i][y]==-1) return;
            else if(arr[i][y]>0) arr[i][y]--;
        }
    }
    else if(d==1)
    {
        for(int i=x+1;i<m;i++)
        {
            if(arr[i][y]==-1||arr[i][y]==0) return;
            else if(arr[i][y]>0) arr[i][y]--;
        }
    }
    else if(d==2)
    {
        for(int i=y-1;i>=0;i--)
        {
            if(arr[x][i]==-1||arr[x][i]==0) return;
            else if(arr[x][i]>0) arr[x][i]--;
        }
    }
    else
    {
        for(int i=y+1;i<n;i++)
        {
            if(arr[x][i]==-1||arr[x][i]==0) return;
            else if(arr[x][i]>0) arr[x][i]--;
        }
    }
}
void add(int x,int y,int d){//up 0 down 1 left 2 right 3
    if(d==0){
        for(int i=x-1;i>=0;i--){
            if(arr[i][y]==-1)return;
            else arr[i][y]++;
        }
    }
    else if(d==1){
        for(int i=x+1;i<m;i++){
            if(arr[i][y]==-1)return;
            else arr[i][y]++;
        }
    }
    else if(d==2){
        for(int i=y-1;i>=0;i--){
            if(arr[x][i]==-1)return;
            else arr[x][i]++;
        }
    }
    else{
        for(int i=y+1;i<n;i++){
            if(arr[x][i]==-1)return;
            else arr[x][i]++;
        }
    }
}
int cnt()
{
    int ans=0;
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<n;j++) if(arr[i][j]!=0) ans++;
    }
    return ans;
}
int main()
{
    ios::sync_with_stdio(0),cin.tie(0);
    cin>>m>>n>>h;
    while(h--)
    {
        cin>>r>>c>>t;
        if(t==0)
        {
            if(arr[r][c]!=0)
            {
                for(int i=0;i<4;i++) if(findNeighbor(r,c,i)) cutWire(r,c,i);
            }
            arr[r][c]=-1;
            for(int i=0;i<4;i++) if(findNeighbor(r,c,i)) add(r,c,i);
        }
        else
        {
            arr[r][c]=0;
            for(int i=0;i<4;i++) if(findNeighbor(r,c,i)) rmv(r,c,i);
        }
        mx=max(mx,cnt());
    }
    cout<<mx<<"\n"<<cnt();
}
```
## ==生產線==
### <font color="0E81A6">題目</font>
[生產線](https://zerojudge.tw/ShowProblem?problemid=g597)
### <font color="0E81A6">核心</font>
BIT、前綴和
### <font color="0E81A6">思路</font>
[BIT教學](https://oi-wiki.org/ds/fenwick/)
學會之後這題就迎刃而解了。
```c++=
#include<bits/stdc++.h>
using namespace std;
#define N 200005
int n,m,machine[N];
long long ans=0;
bool cmp(int a,int b)
{
    return a>b;
}
struct BIT
{
    int sz;
    vector<int> dat;
    void init(int n)
    {
        sz=n;
        dat.assign(sz+2,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()
{
    scanf("%d%d",&n,&m);
    bit.init(n);
    int a,b,w;
    while(m--)
    {
        scanf("%d%d%d",&a,&b,&w);
        bit.upd(a,w);
        bit.upd(b+1,-w);
    }
    vector<int> v;
    for(int i=1;i<=n;i++) v.push_back(bit.sum(i));
    sort(v.begin(),v.end(),cmp);
    for(int i=0;i<n;i++) scanf("%d",machine+i);
    sort(machine,machine+n);
    for(int i=0;i<n;i++) ans+=machine[i]*v[i];
    printf("%lld\n",ans);
}
```
## ==真假子圖==
### <font color="0E81A6">題目</font>
[真假子圖](https://zerojudge.tw/ShowProblem?problemid=g598)
### <font color="0E81A6">核心</font>
並查集、二分圖
### <font color="0E81A6">思路</font>
這題運用到填色和並查集的觀念，屬實漂亮。
```c++=
#include<bits/stdc++.h>
using namespace std;
#define N 20005
#define int long long
int parent[N],color[N]={0},rk[N];
vector<int> edge[N];
int other(int s){return (s%2)?s+1:s-1;}
void init(int col)
{
    for(int i=1;i<=col;i++) parent[i]=i,rk[i]=0;
}
void dfs(int id,int col)
{
    color[id]=col;
    for(auto i:edge[id])
    {
        if(!color[i]) dfs(i,other(col));
    }
}
int findp(int u)
{
    if(parent[u]==u) return u;
    return parent[u]=findp(parent[u]);
}
void join(int u,int v)
{
    int r1=findp(u),r2=findp(v);
    if(r1==r2) return;
    if(rk[r1]<rk[r2]) swap(r1,r2);
    parent[r2]=r1;
    if(rk[r1]==rk[r2]) rk[r1]++;
    return;
}
signed main()
{
    int n,m,p,k,u,v;
    scanf("%lld%lld",&n,&m);
    for(int i=0;i<m;i++)
    {
        scanf("%lld%lld",&u,&v);
        edge[u].push_back(v);
        edge[v].push_back(u);
    }
    int now=1;
    for(int i=0;i<n;i++)
    {
        if(!color[i]) dfs(i,now),now+=2;
    }
    vector<int> ans;
    scanf("%lld%lld",&p,&k);
    for(int i=1;i<=p;i++)
    {
        bool mistake=false;
        init(now);
        for(int j=0;j<k;j++)
        {
            scanf("%lld%lld",&u,&v);
            if(mistake) continue;
            if(findp(color[u])==findp(color[v])) mistake=true,ans.push_back(i);
            else
            {
                join(color[u],other(color[v]));
                join(color[v],other(color[u]));
            }
        }
    }
    for(int i:ans) printf("%lld\n",i);
}
```