P3295-[SCOI2016]萌萌哒【ST表,并查集】
生活随笔
收集整理的這篇文章主要介紹了
P3295-[SCOI2016]萌萌哒【ST表,并查集】
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P3295
題目大意
一個(gè)nnn位的數(shù)字,mmm個(gè)條件給出兩個(gè)完全相同的區(qū)間,求可能的數(shù)字?jǐn)?shù)量。
解題思路
其實(shí)就是區(qū)間中的每個(gè)數(shù)字分別連邊,但是這樣顯然會(huì)TTT。考慮通過(guò)消耗查詢的復(fù)雜度來(lái)平衡詢問(wèn)的復(fù)雜度。
考慮用STSTST表進(jìn)行優(yōu)化,我們定義fi,jf_{i,j}fi,j?的點(diǎn)表示位置[i,i+2j?1][i,i+2^j-1][i,i+2j?1]這個(gè)區(qū)間,顯然只有jjj相同的可以進(jìn)行連邊。
連邊完成之后我們按照區(qū)間長(zhǎng)度從大到小的拆分,對(duì)于每個(gè)點(diǎn),我們讓它的兩個(gè)下層節(jié)點(diǎn)與它父節(jié)點(diǎn)的兩個(gè)下層節(jié)點(diǎn)分開(kāi)連邊就好了。
時(shí)間復(fù)雜度O(nlog?n)O(n\log n)O(nlogn)
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1e5+10,XJQ=1e9+7; int n,m,cnt,f[N][20],p[N*20],fa[N*20],lg; int find(int x) {return fa[x]==x?(x):(fa[x]=find(fa[x]));} void unionn(int x,int y){x=find(x);y=find(y);if(x==y)return;if(x<y)fa[y]=x;else fa[x]=y;return; } int main() {scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)for(int j=0;i+(1<<j)-1<=n;j++)f[i][j]=++cnt,p[cnt]=i,lg=max(lg,j),fa[cnt]=cnt;while(m--){int l1,r1,l2,r2;scanf("%d%d%d%d",&l1,&r1,&l2,&r2);int len=r1-l1+1;for(int i=0;(1<<i)<=len;i++)if((len>>i)&1)unionn(f[l1][i],f[l2][i]),l1+=(1<<i),l2+=(1<<i);}for(int j=lg;j>=1;j--)for(int i=1;i+(1<<j)-1<=n;i++){int x=f[i][j],y=find(x);if(x==y)continue;int ii=p[y];unionn(f[i][j-1],f[ii][j-1]);unionn(f[i+(1<<j-1)][j-1],f[ii+(1<<j-1)][j-1]);}int ans=1;bool flag=1;for(int i=1;i<=n;i++)if(p[find(f[i][0])]==i){if(flag)ans=9,flag=0;else ans=1ll*ans*10%XJQ;}printf("%d\n",ans); }總結(jié)
以上是生活随笔為你收集整理的P3295-[SCOI2016]萌萌哒【ST表,并查集】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: marry的用法 marry是什么意思
- 下一篇: Bzoj3309-DZY Loves M