---
# System prepended metadata

title: TIOJ

---

# TIOJ
## [地雷區](https://tioj.ck.tp.edu.tw/problems/1420)
想法：
每次讀入炸彈座標，如果這裡被其他的炸彈覆蓋過了，那就併入覆蓋他的炸彈，再將他九宮格範圍內的一同併入，如果沒有的話那就自己獨立成新的一群，最後再看有幾群就好。
![](https://hackmd.io/_uploads/SymjD_Y-T.jpg)

sol : (Implementation, dsu, 2d array)
```cpp=
#include<bits/stdc++.h>
#define ll long long
#define rep(a,b,c) for(int a=b; a<c; ++a)
#define pb emplace_back
#define f first
#define s second
#define gao pair<int,int>
using namespace std;
const int maxn=1e5+5;
int mx[8]={-1,-1,-1,0,0,1,1,1};
int my[8]={-1,0,1,-1,1,-1,0,1};
ll exp(ll idx,ll k,ll mod){
    if(k==1) return idx;
    if(k%2) return idx*(exp(idx,k-1,mod))%mod;
    else{
        ll hehe=exp(idx,k/2,mod);
        return hehe*hehe%mod;
    }
}
vector<int> anc(50001,0);
int find(int idx){
    if(idx==anc[idx]) return idx;
    else return anc[idx]=find(anc[idx]);
}
void merge(int a,int b){
    int f1=find(a),f2=find(b);
    if(f1==f2) return;
    anc[f2]=f1;
    return ;
}
void solve(){
    int x,y,b;
    cin>>x>>y>>b;
    int graph[x][y];
    rep(i,0,x){
        rep(j,0,y) graph[i][j]=0;
    }
    rep(i,1,b+1) anc[i]=i;
    rep(i,1,b+1){
        int bx,by;
        cin>>bx>>by;
        bx--,by--;
        if(graph[bx][by]) merge(graph[bx][by],anc[i]);
        else graph[bx][by]=anc[i];
        rep(j,0,8){
            int tx=bx+mx[j],ty=by+my[j];
            if(tx<0||tx>=x||ty<0||ty>=y) continue;
            if(graph[tx][ty]) merge(graph[tx][ty],anc[i]);
            else graph[tx][ty]=anc[i];
        }
    }
    set<int> s;
    rep(i,1,b+1){
        int f=find(i);
        if(s.find(f)==s.end()) s.insert(f);
    }
    cout<<s.size()<<'\n';
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0);
    solve();
}
```

## [貨物運送計畫](https://tioj.ck.tp.edu.tw/problems/1641)
想法：
你開乘會跟我的物理段考一樣裂開，用log來代替乘法，就變加法了。
最後就pow回來，整數部分代表次方，那剩餘的就是你完整的值的樣子。
sol : (math, dijkstra)
```cpp=
#include<bits/stdc++.h>
#define int long long
#define rep(a,b,c) for(int a=b; a<c; ++a)
#define gao pair<int,double>
#define lol pair<double,int>
#define f first
#define s second
#define pb emplace_back
using namespace std;
const int maxn=1e4+5;
const int lim=1e15;
vector<gao> path[maxn];
signed main(){
    ios::sync_with_stdio(0),cin.tie(0);
    int n,m,s,t;
    cin>>n>>m>>s>>t;
    rep(i,0,m){
        int u,v;
        double w;
        cin>>u>>v>>w;
        path[u].pb(v,double(log10(w+1)));
    }
    double dis[maxn];
    rep(i,0,maxn) dis[i]=lim;
    priority_queue<lol,vector<lol>,greater<lol>> pq;
    dis[s]=double(0);
    pq.push({dis[s],s});
    while(!pq.empty()){
        auto t=pq.top();
        pq.pop();
        for(auto son:path[t.s]){
            if(dis[son.f]>t.f+son.s){
                dis[son.f]=t.f+son.s;
                pq.push({dis[son.f],son.f});
            }
        }
    }
    double ans=dis[t];
    int left=floor(ans);
    ans-=left;
    cout<<fixed<<setprecision(2)<<pow(10,ans)<<"e+";
    if(left<100){
        if(left<10) cout<<"00"<<left;
        else cout<<"0"<<left;
    }
    else cout<<left;
    cout<<'\n';
}
```

## [烏龜暗殺 梗](https://tioj.ck.tp.edu.tw/problems/1706)
想法：
仔細看一下會有單調性，要嘛第一天最好，要不然就最後一天，剩下就實作。
sol : (greedy, dijkstra)
```cpp=
#include<bits/stdc++.h>
#define int long long
#define rep(a,b,c) for(int a=b; a<c; ++a)
#define gao pair<int,int>
#define f first
#define s second
#define pb emplace_back
using namespace std;
const int maxn=2e5+5;
const int lim=1e15;
vector<gao> path[maxn];
vector<gao> rev[maxn];
int d1(int start,int end){
    priority_queue<gao,vector<gao>,greater<gao>> pq;
    int dis[maxn];
    rep(i,0,maxn) dis[i]=lim;
    dis[start]=0;
    pq.push({dis[start],start});
    while(!pq.empty()){
        auto t=pq.top();
        pq.pop();
        for(auto son:path[t.s]){
            if(dis[son.f]>t.f+son.s){
                dis[son.f]=t.f+son.s;
                pq.push({dis[son.f],son.f});
            }
        }
    }
    return dis[end];
}
int d2(int start,int end){
    priority_queue<gao,vector<gao>,greater<gao>> pq;
    int dis[maxn];
    rep(i,0,maxn) dis[i]=lim;
    dis[start]=0;
    pq.push({dis[start],start});
    while(!pq.empty()){
        auto t=pq.top();
        pq.pop();
        for(auto son:rev[t.s]){
            if(dis[son.f]>t.f+son.s){
                dis[son.f]=t.f+son.s;
                pq.push({dis[son.f],son.f});
            }
        }
    }
    return dis[end];
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0);
    int n,r,a,b,d;
    cin>>n>>r>>a>>b>>d;
    rep(i,0,r){
        int u,v,c1,p1,c2,p2;
        cin>>u>>v>>c1>>p1>>c2>>p2;
        path[u].pb(v,c1);
        path[v].pb(u,c2);
        rev[u].pb(v,c1+p1*(d-1));
        rev[v].pb(u,c2+p2*(d-1));
    }
    int f1_go=d1(a,b);
    int f1_back=d1(b,a);
    int f2_go=d2(a,b);
    int f2_back=d2(b,a);
    cout<<min(f1_go+f1_back,f2_go+f2_back)<<'\n';
}
```

## [algae](https://tioj.ck.tp.edu.tw/problems/1677)
想法：
可以觀察到數列是費氏數列，但知道這個性質只夠我們找到當天的枝數，
再觀察可以發現，每n項數列剛好也是n-1項跟n-2項合併。(多寫個幾項出來)
所以就從中間猛拆，最後會拆到1或2，這是你絕對知道答案的狀況。
sol : (math, binary search)

```cpp=
#include<bits/stdc++.h>
#define int long long
#define rep(a,b,c) for(int a=b; a<c; ++a)
using namespace std;
int f[101];
void init(){
    f[0]=0;
    f[1]=1;
    rep(i,2,101) f[i]=f[i-1]+f[i-2];
}
void solve(){
    int n,k;
    cin>>n>>k;
    if(f[n]<k) cout<<-1<<'\n';
    else{
        if(n==1) cout<<0<<'\n';
        else if(n==2) cout<<1<<'\n';
        else{
            int t=n;
            while(t>=3){
                if(f[t-2]>=k){
                    t=t-2;
                }
                else{
                    k-=f[t-2];
                    t=t-1;
                }
            }
            cout<<(t==1?0:1)<<'\n';
        }
    }
}
signed main(){
    init();
    int t;
    cin>>t;
    while(t--) solve();
}
```

## [害蟲決戰時刻](https://tioj.ck.tp.edu.tw/problems/1699)
想法：
裸莫隊，只是題敘搞耍，種族的範圍會超大，我沒有離散化被搞翻，謝謝衣服幫我檢查。
詳情明天補，蔡昀熹是馴龍騎士。
```cpp=
#include<bits/stdc++.h>
#define ll long long
#define rep(a,b,c) for(int a=b; a<c; ++a)
#define pb emplace_back
#define f first
#define s second
#define lpos pos*2
#define rpos pos*2+1
#define gao pair<ll,ll>
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
using namespace std;
const int maxn=1e5+5;
struct que{
    int l,r,k,order,kuai;
};
bool cmp(que a,que b){
    if(a.kuai==b.kuai) return a.r<b.r;
    else return a.kuai<b.kuai;
}
que ques[maxn];
vector<int> vec(maxn);
int cnt[maxn]={0},hehe[maxn]={0};
int n,q,ans=0;
void add(int idx){
    hehe[cnt[idx]]--;
    cnt[idx]++;
    hehe[cnt[idx]]++;
    //cout<<ans<<" "<<idx<<'\n';
    ans=max(ans,cnt[idx]);
}
void rem(int idx){
    hehe[cnt[idx]]--;
    cnt[idx]--;
    hehe[cnt[idx]]++;
    while(!hehe[ans]) ans--;
}
void PF(){
    sort(ques,ques+q,cmp);
    int L=1,R=1;
    add(vec[1]);//bruh
    hehe[0]=n;
    bitset<maxn> b;
    b.reset();
    rep(i,0,q){
        while(R<ques[i].r) add(vec[++R]);
        while(L>ques[i].l) add(vec[--L]);
        while(R>ques[i].r) rem(vec[R--]);
        while(L<ques[i].l) rem(vec[L++]);
        if(1.0*ans>=1.0*(ques[i].r-ques[i].l+1)/ques[i].k) b[ques[i].order]=1;
    }
    rep(i,0,q) cout<<(b[i]?"Yes":"No")<<'\n';
}
void solve(){
    cin>>n>>q;
    map<int,int> m;
    rep(i,1,n+1) cin>>vec[i],m[vec[i]]++;
    int stamp=0;
    for(auto &t:m) t.s=++stamp;
    rep(i,1,n+1) vec[i]=m[vec[i]];
    int standard=sqrt(n);
    rep(i,0,q){
        cin>>ques[i].l>>ques[i].r>>ques[i].k;
        ques[i].order=i;
        ques[i].kuai=(ques[i].l/standard);
    }
    PF();
}
int main(){
    ios::sync_with_stdio(0),cin.tie(0);
    solve();
}
```

## [領土](https://tioj.ck.tp.edu.tw/problems/1280https://tioj.ck.tp.edu.tw/problems/1280)
裸凸包
有個可以注意的地方是在convex_hull cross的部分
<0 會把斜率一樣的push_back
<=0 會把斜率一樣的捨棄，如果答案要最少點可以這樣
```cpp=
#include<bits/stdc++.h>
#define int long long
#define rep(a,b,c) for(int a=b; a<c; ++a)
#define pb push_back
#define gao pair<int,int>
#define f first
#define s second
using namespace std;
vector<gao> vec;
gao operator - (gao x,gao y){
    return {x.f-y.f,x.s-y.s};
}
int cross(gao x,gao y){
    return x.f*y.s-x.s*y.f;
}
vector<gao> convex_hull(){
    vector<gao> ret;
    sort(vec.begin(),vec.end());
    rep(i,0,2){
        int t=ret.size();
        for(auto pt: vec){
            while(ret.size()-t>=2&&cross(ret.back()-ret[ret.size()-2],pt-ret[ret.size()-2])<0) ret.pop_back();
            ret.pb(pt);
        }
        ret.pop_back();
        reverse(vec.begin(),vec.end());
    }
    return ret;
}
void solve(){
    int n;
    cin>>n;
    vec.resize(n);
    rep(i,0,n){
        cin>>vec[i].f>>vec[i].s;
    }
    vector<gao> ans=convex_hull();
    //for(auto t:ans) cout<<t.f<<" "<<t.s<<'\n';
    int b=ans.size();
    int cnt=0;
    ans.pb(ans.front());
    rep(i,0,b){
        cnt+=(cross(ans[i],ans[i+1]));
        //cout<<cnt<<" ";
    }
    cout<<cnt/2+cnt%2<<'\n';
}
signed main(){
    ios::sync_with_stdio(0),cin.tie(0);
    solve();
}

```