比賽的時候根據數據范圍馬上猜出了是通過輕重點分塊,但是在維護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; }