重新振作第8天----日常小記

菜dog的日常生活發表於2024-11-28

今天依舊是墮落無比,早起不了一點。因為白天沒課,直接睡到三點,除了中午起來背了半小時單詞。。。。。

六級單詞

學了too much time 的單詞,感覺現在有印象,但是估計過幾天就忘記了。估計得熟練

資料庫實驗報告

預計9點到12點寫完差不多三分實驗報告?

退役者的每日一題3

題目連結:https://atcoder.jp/contests/abc380/tasks/abc380_e

思路分析:
首先,肯定想到是使用並查集進行維護,但是當時看錯題了,以為是所有和x相同顏色的格子,結果是祥林的。相鄰的其實我並不太會,在參考了別人的題解之後,發現只要額外多開闢兩個陣列即可。這裡總共開闢了五個陣列,cnt,fa,l,r,col分別維護區間塊的點數、父親、左邊界、右邊界以及顏色。對於塊的合併,我們需要當這個塊的顏色改變後,如果和左右相鄰塊的顏色是一樣的,那我們需要將左塊的左邊界變成合並後的左邊界,右塊的右邊界要變成合並後的右邊界即可。

程式碼實現:

#include<bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
const int N=5e5+10;
const int MAX=1e6+5;
const int mod=1E9+7;
int n,m,k,w;
int fa[N];
int cnt[N],l[N],r[N],col[N];
void init(int n){
    for(int i=1;i<=n;i++){
        fa[i]=l[i]=r[i]=col[i]=i;
        cnt[i]=1;
    }
}
int findfa(int x){
    if(fa[x]!=x)
    return fa[x]=findfa(fa[x]);
    return x;
}
void merge(int x,int y){
    int fx=findfa(x);
    // 中間的
    cnt[col[fx]]-=r[fx]-l[fx]+1;
    col[fx]=y;
    cnt[y]+=r[fx]-l[fx]+1;

    // 問右邊
    if(r[fx]!=n){
        int fr=findfa(r[fx]+1);
        if(col[fr]==y){
            r[fx]=r[fr];
            fa[fr]=fx;
        }
    }

    // 問左邊
    if(l[fx]!=1){
        int fl=findfa(l[fx]-1);
        if(col[fl]==y){
            l[fx]=l[fl];
            fa[fl]=fx;
        }
    }
    
}
void solve(){
    int n,q;
    cin>>n>>q;
    init(n);
    int op,x,y;
    while(q--){
        cin>>op;
        if(op==1){
            cin>>x>>y;
            merge(x,y);
        }
        else {
            cin>>x;
            cout<<cnt[x]<<endl;
        }
    }
}
signed main(){
    int t;
    t=1;
    //cin>>t;
    while (t--){
        solve();
    }
    return 0;
}

相關文章