この質問は非常に巧妙で、新しい遅延ラベルの関係について説明しています。。
通常の線分ツリーは、n * 4のスペースを使用してシーケンスを記述します。そのため、間隔に対して、1つのポイントに対応するログポイントが存在する場合があります。
線分ツリーは、クエリログを作成するために可能な限り最小のスペースを使用します
stテーブルはnlognのスペースです。間隔のセクションでは、1対1の対応を実現できます。ラインツリーよりも暴力的なのは前処理だけです。
したがって、この質問を線分ツリーに配置する場合は、2つの区間を分割し、線分ツリーのノードの親配列を更新する必要があります。
散在する点はlog ^ 2である可能性があり、点をマークするのは面倒です
stテーブルの場合、間隔の長さは1対1の対応であるため、2つのマークのみが必要であり、重複するマークはユニオン検索と組み合わされます。
次に、これは、線分ツリーの列挙の単一ポイントクエリ操作と同等です。レイヤーごとのプッシュダウン(レイヤーごとではありませんが、面倒です)
暴力的なユニオン検索セットに対するこの質問の最適化は、間隔にユニオン検索セットを使用し、遅延マーカーの重ね合わせを使用して繰り返し操作を減らすことです。
コード:
#include<iostream>
#include<cstdio>
#define P 1000000007
using namespace std;
int f[100005][25],o,n,m,i,j,er[25],l1,l2,r1,r2,cnt,ans;
int zhao(int o,int x)
{
if(f[o][x]!=o)f[o][x]=zhao(f[o][x],x);
return f[o][x];
}
int main()
{
scanf("%d%d",&n,&m);
er[0]=1;
for(i=1;i<=20;i++)er[i]=er[i-1]*2;
for(i=1;i<=n;i++)
for(j=0;j<=20;j++)
f[i][j]=i;
for(j=1;j<=m;j++)
{
scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
int o=r1-l1+1;
for(i=0;i<=20;i++)
if(er[i]&o)
{
int f1=zhao(f[l1][i],i),f2=zhao(f[l2][i],i);
if(f1!=f2)f[f1][i]=f2;
l1+=er[i];
l2+=er[i];
}
}
for(j=20;j>=1;j--)
{
for(i=1;i<=n;i++)
{
//分下去
if(i+er[j]-1>n)continue;
o=zhao(i,j);
int ll=zhao(o,j-1);
int lll=zhao(i,j-1);
f[ll][j-1]=lll;
int rr=zhao(o+er[j-1],j-1);
int rrr=zhao(i+er[j-1],j-1);
f[rr][j-1]=rrr;
}
}
for(i=1;i<=n;i++)
if(zhao(i,0)==i)++cnt;
ans=9;
for(i=1;i<cnt;i++)
ans=1ll*ans*10%P;
printf("%d",ans);
}