jzoj6257. 【省选模拟8.9】修路

Description
在这里插入图片描述

Input
在这里插入图片描述

Output
在这里插入图片描述

Sample Input
Sample Input 1
5
1 2 3 4 5
1 2
2 3
2 4
3 5

Sample Input 2
10
1 7 3 4 8 6 2 9 10 5
1 2
1 3
2 4
3 5
2 6
3 7
4 8
5 9
6 10

Sample Output
Sample Output 1
0
0
0
2

Sample Output 2
0
0
0
1
1
0
1
2
3

Data Constraint
在这里插入图片描述

题解

可以发现染色操作类似LCT
而LCT的时间复杂度(操作的splay树总数)为n log n,对应本题就是总操作颜色块为n log n
所以LCT维护颜色+树状数组算答案

code

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define low(x) (x&-(x))
using namespace std;

struct type{
    
    
	int s,id;
} A[100001];
int tr[100001][4]; //2=size 3=color
int fa[100001];
int C[100001];
int p[100001][2];
long long Tr[100001];
int n,i,j,k,l,I,x,y;
long long ans;

bool cmp(type a,type b)
{
    
    
	return a.s<b.s;
}

void rot(int t)
{
    
    
	int Fa=fa[t],Fa2=fa[Fa],s,x,x2;
	
	x=tr[Fa][1]==t;
	x2=tr[Fa2][1]==Fa;
	
	s=tr[t][x^1];
	
	tr[t][3]=tr[Fa][3];
	tr[Fa][3]=0;
	
	tr[Fa][2]=tr[tr[Fa][x^1]][2]+tr[tr[t][x^1]][2]+1;
	tr[t][2]=tr[tr[t][x]][2]+tr[Fa][2]+1;
	
	fa[s]=Fa;
	tr[Fa][x]=s;
	
	fa[Fa]=t;
	tr[t][x^1]=Fa;
	
	fa[t]=Fa2;
	if (!tr[t][3])
	tr[Fa2][x2]=t;
}

void splay(int t)
{
    
    
	int Fa,Fa2;
	
	while (!tr[t][3])
	{
    
    
		Fa=fa[t];
		
		if (!tr[Fa][3])
		{
    
    
			Fa2=fa[Fa];
			
			if ((tr[Fa2][0]==Fa)^(tr[Fa][0]==t)==1)
			rot(t),rot(t);
			else
			rot(Fa),rot(t);
		}
		else
		rot(t);
	}
}

void change(int t,int s)
{
    
    
	while (t<=n)
	{
    
    
		Tr[t]+=s;
		t+=low(t);
	}
}

long long find(int t)
{
    
    
	long long ans=0;
	
	while (t)
	{
    
    
		ans+=Tr[t];
		t-=low(t);
	}
	
	return ans;
}

int main()
{
    
    
	freopen("road.in","r",stdin);
	freopen("road.out","w",stdout);
	
	scanf("%d",&n);
	fo(i,1,n)
	{
    
    
		scanf("%d",&C[i]);
		
		A[i].s=C[i];
		A[i].id=i;
	}
	
	sort(A+1,A+n+1,cmp);
	
	j=0;
	fo(i,1,n)
	{
    
    
		if (i==1 || A[i].s!=A[i-1].s)
		++j;
		C[A[i].id]=j;
	}
	
	fo(i,1,n)
	{
    
    
		tr[i][2]=1;
		tr[i][3]=C[i];
	}
	
	fo(I,2,n)
	{
    
    
		scanf("%d%d",&x,&y);
		
		l=0;
		
		i=x;
		j=0;
//		access
		while (i)
		{
    
    
			splay(i);
			
			tr[i][2]-=tr[tr[i][1]][2];
			tr[tr[i][1]][3]=tr[i][3];
			
			tr[i][1]=0;
			
			++l;
			p[l][0]=tr[i][3];
			p[l][1]=tr[i][2];
			
			if (j)
			{
    
    
				tr[i][1]=j;
				
				tr[j][3]=0;
				tr[i][2]+=tr[j][2];
			}
			
			j=i;
			i=fa[i];
		}
		tr[j][3]=C[y];
		fa[y]=x;
		
		ans=0;
		fo(i,1,l)
		{
    
    
			ans+=find(p[i][0]-1)*p[i][1];
			change(p[i][0],p[i][1]);
		}
		
		printf("%lld\n",ans);
		
		fo(i,1,l)
		change(p[i][0],-p[i][1]);
	}
}

猜你喜欢

转载自blog.csdn.net/gmh77/article/details/99046013