日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

HDU - 6756 Finding a MEX-分块思想

發(fā)布時(shí)間:2023/12/3 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDU - 6756 Finding a MEX-分块思想 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

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

題目大意:給你一個(gè)無(wú)向圖,每個(gè)點(diǎn)有權(quán)值a,將f(u)定義為對(duì)u的鄰居的集合求mex;

有兩個(gè)操作:

1:將u的權(quán)值修改為x

2:查詢f(u)

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

先預(yù)處理分塊。

修改操作:

如果為小點(diǎn),則直接修改他的所有鄰居

如果為大點(diǎn),我們就先不修改他的鄰居,我們使用一個(gè)容器來(lái)記錄大點(diǎn)的鄰居(大點(diǎn)不會(huì)很多的)的當(dāng)前貢獻(xiàn),等到在查詢的時(shí)候,我們會(huì)先遍歷一遍大點(diǎn)的鄰居,如果鄰居當(dāng)前的貢獻(xiàn)不等于鄰居現(xiàn)在的權(quán)值的話,說(shuō)明該大點(diǎn)鄰居已經(jīng)被修改過(guò)了,那么我們直接修改該鄰居的貢獻(xiàn)。

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

#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;//答案不會(huì)超過(guò)他的度數(shù)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);//每個(gè)點(diǎn)塊內(nèi)的大小tag[i].resize(du[i]/block_size+2);//每個(gè)點(diǎn)快的數(shù)量for(int v:g[i]){if(du[v]>block_size){big_n[i].push_back({v,a[v]});//記錄大點(diǎn)鄰居}_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){//小點(diǎn)直接修改for(int v:g[u]){_del(v,a[u]);_insert(v,k);}}a[u]=k;}else {for(pii &v:big_n[u]){//先查詢大點(diǎn)鄰居的值是否改變。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; }

總結(jié)

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

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。