給定一個整數序列爲1到n的排列,給出連邊的命令,從一個區間選出最大最小值相連,給出詢問,問兩個點是否連通。

#include<cstdio>
#include<string.h>
#include<iostream>
#include<cmath>
#include<cstdlib>

using namespace std;

int n,m,k;
struct node
{
	int minn,maxx;
};
#define maxv 101100
node arr[maxv];
int input[maxv];
int c;
int parent[maxv];

void buildtree(int s,int e,int &maximal,int& minimal)
{
	if(e-s+1<=0)
	{
		maximal=minimal=-1;
		return;
	}
	if(e-s+1==0)
	{
		maximal=minimal=input[e];
		return;
	}
	if(e-s+1==2)
	{
		maximal=max(input[s],input[e]);
		minimal=min(input[s],input[e]);
		return;
	}
	int temp=(s+e)/2;
	arr[temp].maxx=input[temp];
	arr[temp].minn=input[temp];
	int i,j;
	buildtree(s,temp-1,i,j);
	if(i>=0&&j>=0)
	{
		if(i>arr[temp].maxx)arr[temp].maxx=i;
		if(j<arr[temp].minn)arr[temp].minn=j;
	}
	buildtree(temp+1,e,i,j);
	if(i>=0&&j>=0)
	{
		if(i>arr[temp].maxx)arr[temp].maxx=i;
		if(j<arr[temp].minn)arr[temp].minn=j;
	}
	maximal=arr[temp].maxx;
	minimal=arr[temp].minn;
	
}

void init()
{
	int i,j;
	buildtree(0,n-1,i,j);
}

void searchtree(int s,int e,int &maximal,int &minimal,int u,int v)
{
	if(e-s+1<=0)
	{
		maximal=minimal=-1;
		return;
	}
	if(s==u&&v==e)
	{
		if(e-s+1<=0)
		{
			maximal=minimal=-1;
			return;
		}
		if(e-s+1==1)
		{
			maximal=minimal=input[e];
			return;
		}
		if(e-s+1==2)
		{
			maximal=max(input[s],input[e]);
			minimal=min(input[e],input[s]);
			return;
		}
		maximal=arr[(s+e)/2].maxx;
		minimal=arr[(s+e)/2].minn;
		return;
	}
	int temp=(s+e)/2;
	int i,j;
	if(u<=temp&&temp<=v)
	{
		maximal=input[temp];
		minimal=input[temp];
		if(u<=temp-1)
		{
			searchtree(s,temp-1,i,j,u,temp-1);
			if(i>maximal)maximal=i;
			if(j>=0&&j<minimal)minimal=j;
		}
		if(v>=temp+1)
		{
			searchtree(temp+1,e,i,j,temp+1,v);
			if(i>maximal)maximal=i;
			if(j>=0&&j<minimal)minimal=j;
		}
		return;
	}
	if(u>temp)
	{
		searchtree(temp+1,e,maximal,minimal,u,v);
		return;
	}
	searchtree(s,temp-1,maximal,minimal,u,v);
}

int find(int a)
{
	int i=a;
	while(parent[a]>=0)
	a=parent[a];
	while(i!=a)
	{
		int temp=parent[i];
		parent[i]=a;
		i=temp;
	}
	return a;
}

void unionset(int a,int b)
{
	int i=find(a),j=find(b);
	if(i==j)return;
	if(i<j)
	{
		parent[j]=i;
		parent[i]--;
	}
	else
	{
		parent[i]=j;
		parent[j]--;
	}
	
}

void process()
{
	int i;
	if(c!=0)
	cout<<endl;
	c++;
	cout<<"CASE "<<c<<endl;
	for(i=0;i<n;i++)
	{
		cin>>input[i];
		input[i]--;
		parent[i]=-1;
	}
	init();
	cin>>m;
	int u,v;
	for(i=0;i<m;i++)
	{
		cin>>u>>v;
		u--,v--;
		searchtree(0,n-1,u,v,u,v);
		unionset(u,v);
	}
	cin>>k;
	for(i=0;i<k;i++)
	{
		cin>>u>>v;
		u--,v--;
		if(find(u)==find(v))
		cout<<"YES"<<endl;
		else
		cout<<"NO"<<endl;
		
	}
}

int main()
{
	while(cin>>n)
	{
		process();
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章