bzoj4569 [Scoi2016]孟達と検索コレクション+ stリスト

この質問は非常に巧妙で、新しい遅延ラベルの関係について説明しています。

通常の線分ツリーは、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);
}



おすすめ

転載: blog.csdn.net/haobang866/article/details/79263706