2020杭電多校(一) Finding a MEX(分塊)


比賽的時候根據數據范圍馬上猜出了是通過輕重點分塊,但是在維護set的時候犯了一個nt錯誤

選擇了插入鄰邊的權值去判斷第一個未出現的答案,怎么想都覺得復雜度很高。

其實可以選擇先插入所有得可能答案,然后對鄰邊影響得答案進行刪除,這樣set中得第一個元素就是答案。

這題復雜度保證得原因是,通過分塊,對於邊數大於1000的稱為重點,去維護一個set,因為邊總共只有1e5條,這樣的點不會超過100個,並且只需要維護從0-度數這樣長度的set就行

后面的值肯定不會影響答案。

對於輕點,只需要暴力枚舉所有的邊去暴力判斷,因為輕點鄰邊不會超過1000條,所以復雜度也得到保證

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
const int mod=998244353;
vector<int> g[N];
set<int> s[N];
int in[N];
int num[110][N];
int id[N];
bool st[N];
int a[N];
vector<int> now[N];
int main(){
    ios::sync_with_stdio(false);
    int i;
    int t;
    cin>>t;
    while(t--){
        int n,m;
        cin>>n>>m;
        int i;
        for(i=1;i<=n;i++)
            cin>>a[i];
        for(i=1;i<=n;i++){
            g[i].clear();
            in[i]=0;
            now[i].clear();
        }
        int block=1000;
        for(i=1;i<=m;i++){
            int x,y;
            cin>>x>>y;
            g[x].push_back(y);
            g[y].push_back(x);
            in[x]++,in[y]++;
        }
        int cnt=0;
        for(i=1;i<=n;i++){
            if(in[i]>=block){
                id[i]=++cnt;//ÀëÉ¢»¯Ó³Éä
                int j;
                s[cnt].clear();
                for(j=0;j<=in[i];j++){
                    s[cnt].insert(j),num[cnt][j]=0;
                }
            }
        }
        for(i=1;i<=n;i++){
            int j;
            for(j=0;j<g[i].size();j++){
                int u=g[i][j];
                if(in[u]>=block){
                    if(a[i]<=in[u]){
                        if(++num[id[u]][a[i]]==1){
                            s[id[u]].erase(a[i]);
                        }
                        now[i].push_back(u);
                    }
                }
            }
        }
        int q;
        cin>>q;
        while(q--){
            int opt;
            cin>>opt;
            if(opt==1){
                int x,y;
                cin>>x>>y;
                for(auto tmp:now[x]){
                    if(y<=in[tmp]){
                        if(++num[id[tmp]][y]==1)
                            s[id[tmp]].erase(y);
                    }
                    if(a[x]<=in[tmp]){
                        if(--num[id[tmp]][a[x]]==0){
                            s[id[tmp]].insert(a[x]);
                        }
                    }
                }
                a[x]=y;
            }
            else{
                int x;
                cin>>x;
                if(in[x]>=block){
                    cout<<*s[id[x]].begin()<<endl;
                }
                else{
                    for(i=0;i<g[x].size();i++){
                        int v=g[x][i];
                        if(a[v]<=in[x]){
                            st[a[v]]=1;
                        }
                    }
                    int ans=0;
                    while(st[ans])
                        ans++;
                    cout<<ans<<endl;
                    for(i=0;i<g[x].size();i++){
                        int v=g[x][i];
                        if(a[v]<=in[x]){
                            st[a[v]]=0;
                        }
                    }
                }
            }
        }
    }
    return 0;
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM