日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

HDU - 6756 Finding a MEX-分块思想

發布時間:2023/12/3 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDU - 6756 Finding a MEX-分块思想 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

https://vjudge.net/problem/HDU-6756

題目大意:給你一個無向圖,每個點有權值a,將f(u)定義為對u的鄰居的集合求mex;

有兩個操作:

1:將u的權值修改為x

2:查詢f(u)

數據量在1e5,可以考慮分塊,我們按照每個點的度數將點分為大小點,小于sqrt(n)的為小點,否則為大點。

先預處理分塊。

修改操作:

如果為小點,則直接修改他的所有鄰居

如果為大點,我們就先不修改他的鄰居,我們使用一個容器來記錄大點的鄰居(大點不會很多的)的當前貢獻,等到在查詢的時候,我們會先遍歷一遍大點的鄰居,如果鄰居當前的貢獻不等于鄰居現在的權值的話,說明該大點鄰居已經被修改過了,那么我們直接修改該鄰居的貢獻。

查詢操作:直接分塊查詢mex,先查詢每個快是不是滿了,不滿的話說明答案就在這個塊中。
?

#include <iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <queue> #include <string> #include <cstring> #include <map> #include <stack> #include <set> #include <cstdlib> #define INF 0x3f3f3f3f3f3f3f3f #define inf 0x3f3f3f3f #define FILL(a,b) (memset(a,b,sizeof(a))) #define lson rt<<1 #define rson rt<<1|1 #define lowbit(a) ((a)&-(a)) #define ios std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0); #define fi first #define sc second #define scd(a) scanf("%d",&a) #define scdd(a,b) scanf("%d%d",&a,&b) #define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c) #define ac cout<<ans<<"\n" #define pb push_back using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<ll,ll> pii; int dx[4]= {-1,1,0,0},dy[4]= {0,0,1,-1}; const ll mod=1e9+7; const ll N =1e5+10; const ll M =250000; const double eps = 1e-4; //const double pi=acos(-1); ll qk(ll a,ll b){ll ans=1;while(b){if(b&1) ans=(ans*a)%mod;a=(a*a)%mod;b/=2;}return ans%mod;} int a[N],block_size=0; vector<int> g[N]; vector<int>tag[N],cnt[N]; vector<pii>big_n[N]; int n,m; int du[N]; void _insert(int u,int sum){if(sum>du[u]) sum=du[u]+1;//答案不會超過他的度數cnt[u][sum]++;if(cnt[u][sum]==1) tag[u][sum/block_size]++; } void _del(int u,int sum){if(sum>du[u]) sum=du[u]+1;cnt[u][sum]--;if(cnt[u][sum]==0) tag[u][sum/block_size]--; } void build(){for(int i=1;i<=n;i++){cnt[i].resize(du[i]+2);//每個點塊內的大小tag[i].resize(du[i]/block_size+2);//每個點快的數量for(int v:g[i]){if(du[v]>block_size){big_n[i].push_back({v,a[v]});//記錄大點鄰居}_insert(i,a[v]);}} } int q1(int u){for(int i=0;i<=du[u]/block_size;i++){//分塊查詢int k=tag[u][i];if(k==block_size) continue;for(int j=i*block_size;j<i*block_size+block_size;j++){if(!cnt[u][j]) return j;}} } void sovle(){scanf("%d%d",&n,&m);block_size=sqrt(n);for(int i=1;i<=n;i++) scd(a[i]);for(int i=1;i<=m;i++){int u,v;scdd(u,v);g[u].push_back(v);g[v].push_back(u);du[u]++;du[v]++;}build();int q;scd(q);//cout<<1<<endl;while(q--){int x, u;scanf("%d%d",&x,&u);if(x==1){int k;scanf("%d",&k);if(du[u]<=block_size){//小點直接修改for(int v:g[u]){_del(v,a[u]);_insert(v,k);}}a[u]=k;}else {for(pii &v:big_n[u]){//先查詢大點鄰居的值是否改變。if(a[v.fi]!=v.se){_del(u,v.se);_insert(u,a[v.fi]);v.se=a[v.fi];}}printf("%d\n",q1(u));}}for(int i=1;i<=n;i++) g[i].clear(),big_n[i].clear(),tag[i].clear(),cnt[i].clear(),du[i]=0; } int main() { #ifdef LOCALfreopen("in.txt", "r", stdin); #else//iosint t=1;cin>>t;while(t--) sovle(); #endif // LOCALreturn 0; }

總結

以上是生活随笔為你收集整理的HDU - 6756 Finding a MEX-分块思想的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。