$$AVICII$$

倍增并查集

 

适用于一个区间向另一个区间连边,形如:

for(int i=1;i<=r1-l1+1;++i)
    merge(l1+i-1,l2+i-1);

开log个并查集,用表示的区间左端点编号,合并的时候像RMQ一样拆区间,递归即可

每个$2^i$的i最多合并$n-1$次,复杂度$O(n*logn)$

 

萌萌哒:

统计最后的集合个数x,答案为$10^{x-1}*9$

 1 #include<bits/stdc++.h>
 2 #define MAXN 100005
 3 #define LL long long
 4 using namespace std;
 5 const int mod=1e9+7;
 6 inline int read(){
 7     int s=0,w=0;char ch=getchar();
 8     while(ch<'0'||ch>'9')w|=(ch=='-'),ch=getchar();
 9     while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
10     return w?-s:s;
11 }
12 #define kd (read())
13 inline int qpow(int a,int b){
14     int res=1;
15     for(;b;b>>=1,a=(LL)a*a%mod)
16         if(b&1)res=(LL)res*a%mod;
17     return res;
18 }
19 int n,m;
20 int fat[18][MAXN],LOG[MAXN];
21 inline int find(int x,int I){
22     return fat[I][x]=fat[I][x]==x?x:find(fat[I][x],I);
23 }
24 int sum=0;
25 void fenzhi(int x,int y,int I){
26     if(find(x,I)==find(y,I))return ;
27     fat[I][find(x,I)]=find(y,I);
28     if(!I)return sum--,void();
29     fenzhi(x,y,I-1);
30     fenzhi(x+(1<<I-1),y+(1<<I-1),I-1);
31     return ;
32 }
33 int main(){
34     n=kd;m=kd;
35     for(int i=2;i<=n;++i)
36         LOG[i]=LOG[i>>1]+1;
37     for(int i=1;i<=n;++i)
38         for(int j=0;j<18;++j)
39             fat[j][i]=i;
40     sum=n;
41     int l1,l2,r1,r2,k;
42     while(m--){
43         l1=kd,r1=kd,l2=kd,r2=kd;
44         k=LOG[r1-l1+1];
45         fenzhi(l1,l2,k);
46         fenzhi(r1-(1<<k)+1,r2-(1<<k)+1,k);
47     }printf("%d\n",9LL*qpow(10,sum-1)%mod);
48     return 0;
49 }
View Code

 

Endless:

平方串套路对于每个长度$x$,标记$\frac{n}{x}$个关键点,每个关键点$i$,统计$i$和$i-1$的最长公共后缀+$i$和$i+1$的最长公共前缀,得到的区间所有长度为二倍$x$的串都是平方串,用$hash$二分或者$sa$,然后倍增并查集。因为考虑最小生成树,所以x按权值排序枚举,每次递归到$2^0$以为着加边。

  1 #include<bits/stdc++.h>
  2 #define MAXN 300005
  3 #define LL long long
  4 using namespace std;
  5 const LL mo1=1e9+7,mo2=998244353,p=1e6;
  6 inline int read(){
  7     int s=0,w=0;char ch=getchar();
  8     while(ch<'0'||ch>'9')w|=(ch=='-'),ch=getchar();
  9     while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
 10     return w?-s:s;
 11 }
 12 #define kd (read())
 13 int n;
 14 int a[MAXN];
 15 int LOG[MAXN];
 16 int fat[20][MAXN];
 17 LL qsm1[MAXN],qsm2[MAXN],bin1[MAXN],bin2[MAXN];
 18 inline LL cal1(int l,int r){
 19     return (qsm1[r]-qsm1[l-1]*bin1[r-l+1]%mo1+mo1)%mo1;
 20 }
 21 inline LL cal2(int l,int r){
 22     return (qsm2[r]-qsm2[l-1]*bin2[r-l+1]%mo2+mo2)%mo2;
 23 }
 24 struct node{
 25     int len,val;
 26     friend bool operator <(const node &a,const node &b){
 27         return a.val<b.val;
 28     }
 29 }Q[MAXN>>1];
 30 inline int find(int x,int I){
 31     return fat[I][x]==x?x:fat[I][x]=find(fat[I][x],I);
 32 }
 33 long long ans=0;
 34 void fenzhi(int x,int y,int I,int w){
 35     if(find(x,I)==find(y,I))return ;
 36     fat[I][find(x,I)]=find(y,I);
 37     if(!I)return ans+=w,void();
 38     fenzhi(x,y,I-1,w),fenzhi(x+(1<<I-1),y+(1<<I-1),I-1,w);
 39     return ;
 40 }
 41 void merge(int l1,int r1,int l2,int r2,int w){
 42     int k=LOG[r1-l1+1];
 43     fenzhi(l1,l2,k,w),fenzhi(r1-(1<<k)+1,r2-(1<<k)+1,k,w);
 44     return ;
 45 }
 46 void work(){
 47     n=kd;ans=0;
 48     for(int i=1;i<=n;++i){
 49         a[i]=kd;
 50         qsm1[i]=(qsm1[i-1]*p%mo1+a[i])%mo1;
 51         qsm2[i]=(qsm2[i-1]*p%mo2+a[i])%mo2;
 52         for(int j=0;j<=19;++j)fat[j][i]=i;
 53     }
 54     for(int i=1;i<=(n>>1);++i)
 55         Q[i].val=kd,Q[i].len=i;
 56     sort(Q+1,Q+(n>>1)+1);
 57     for(int I=1;I<=(n>>1);++I){
 58         int len=Q[I].len,w=Q[I].val;
 59         //cout<<len<<" "<<w<<endl;
 60         for(int i=1;i<=n;i+=len){
 61             int L,R;
 62             if(i!=1){
 63                 int rr=min(i+len-1,n);
 64                 int l=0,r=min(len,min(i+len-1,n)-i+1);
 65                 while(r-l>1){
 66                     int mid=l+r>>1;
 67                     if(cal1(rr-mid+1,rr)==cal1(i-1-mid+1,i-1)
 68                      &&cal2(rr-mid+1,rr)==cal2(i-1-mid+1,i-1))
 69                         l=mid;
 70                     else r=mid;
 71                 }
 72                 if(cal1(rr-r+1,rr)==cal1(i-1-r+1,i-1)
 73                  &&cal2(rr-r+1,rr)==cal2(i-1-r+1,i-1))
 74                 L=i-1-r+1;
 75                 else L=i-1-l+1;
 76             }else L=i;
 77             if(i+len<=n){
 78                 int l=0,r=min(len,min(i+2*len-1,n)-(i+len)+1);
 79                 while(r-l>1){
 80                     int mid=l+r>>1;
 81                     if(cal1(i,i+mid-1)==cal1(i+len,i+len+mid-1)
 82                      &&cal2(i,i+mid-1)==cal2(i+len,i+len+mid-1))
 83                         l=mid;
 84                     else r=mid;
 85                 }
 86                 if(cal1(i,i+r-1)==cal1(i+len,i+len+r-1)
 87                  &&cal2(i,i+r-1)==cal2(i+len,i+len+r-1))
 88                 R=i+len+r-1;
 89                 else R=i+len+l-1;
 90             }else R=min(i+len-1,n);
 91             //cout<<"HH "<<i<<" "<<L<<" "<<R<<endl;
 92             if(R-L+1>=2*len){
 93                 //cout<<L<<" "<<R-len<<" "<<L+len<<" "<<R<<endl;
 94                 merge(L,R-len,L+len,R,w);
 95             }
 96         }
 97     }printf("%lld\n",ans);
 98     return ;
 99 }
100 int main(){
101     //freopen("1.in","r",stdin);
102     freopen("endless.in","r",stdin);
103     freopen("endless.out","w",stdout);
104     bin1[0]=bin2[0]=1;
105     for(int i=1;i<=3e5;++i)bin1[i]=bin1[i-1]*p%mo1,bin2[i]=bin2[i-1]*p%mo2;
106     for(int i=2;i<=3e5;++i)LOG[i]=LOG[i>>1]+1;
107     int T=kd;
108     while(T--)work();
109     return 0;
110 }
View Code

 

posted @ 2020-06-08 21:10  bootpuss  阅读(194)  评论(0编辑  收藏  举报