P3295-[SCOI2016]萌萌哒【ST表,并查集】
生活随笔
收集整理的這篇文章主要介紹了
P3295-[SCOI2016]萌萌哒【ST表,并查集】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P3295
題目大意
一個nnn位的數字,mmm個條件給出兩個完全相同的區間,求可能的數字數量。
解題思路
其實就是區間中的每個數字分別連邊,但是這樣顯然會TTT??紤]通過消耗查詢的復雜度來平衡詢問的復雜度。
考慮用STSTST表進行優化,我們定義fi,jf_{i,j}fi,j?的點表示位置[i,i+2j?1][i,i+2^j-1][i,i+2j?1]這個區間,顯然只有jjj相同的可以進行連邊。
連邊完成之后我們按照區間長度從大到小的拆分,對于每個點,我們讓它的兩個下層節點與它父節點的兩個下層節點分開連邊就好了。
時間復雜度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); }總結
以上是生活随笔為你收集整理的P3295-[SCOI2016]萌萌哒【ST表,并查集】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: marry的用法 marry是什么意思
- 下一篇: Bzoj3309-DZY Loves M