Codeforces 643D. Bearish Fanpages 题解

题目链接:D. Bearish Fanpages

题目大意:洛谷


题解:做这一道题的主要任务,读题,读题,读题……(我能说我题目读了将近 1h 吗

因为是基环树,所以考虑在树上怎么做,大概就是维护每一个节点的孩子对它的贡献,然后父亲单独拎出来处理一下就行了。

放到基环树上呢?

维护后继是它的节点,然后把它的后继单独拎出来处理一下,然后,因为出题人保证了点不会重复,所以直接拿 set 维护就可以了。

代码有点长,细节有点多(比起某毒瘤出的数据结构题来说好多了)。

下面是代码:

#include <set>
#include <cstdio>
using namespace std;
template<typename Elem>
void read(Elem &a){
	a=0;
	char c=getchar();
	while(c<'0'||c>'9'){
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		a=(a<<1)+(a<<3)+(c^48);
		c=getchar();
	}
}
typedef long long ll;
const int Maxn=100000;
int n,q;
int deg[Maxn+5],f[Maxn+5];
bool vis[Maxn+5];
ll a[Maxn+5],t[Maxn+5];
multiset<ll> s[Maxn+5];
void del(int x){
	if(vis[x]&&!s[x].empty()){
		vis[x]=0;
		s[0].erase(s[0].find((*s[x].begin())+t[x]/(deg[x]+1)));
		s[0].erase(s[0].find((*(--s[x].end()))+t[x]/(deg[x]+1)));
	}
}
void add(int x){
	if(!vis[x]&&!s[x].empty()){
		vis[x]=1;
		s[0].insert((*s[x].begin())+t[x]/(deg[x]+1));
		s[0].insert((*(--s[x].end()))+t[x]/(deg[x]+1));
	}
}
void work(int i,int j){
	del(f[i]);
	del(f[f[i]]);
	del(f[f[f[i]]]);
	del(j);
	del(f[j]);
	del(f[f[j]]);
	s[f[i]].erase(s[f[i]].find(a[i]));
	s[f[f[i]]].erase(s[f[f[i]]].find(a[f[i]]));
	a[f[i]]-=t[i]/(deg[i]+1);
	a[f[i]]-=t[f[i]]-deg[f[i]]*(t[f[i]]/(deg[f[i]]+1));
	a[f[i]]+=t[f[i]]-(deg[f[i]]-1)*(t[f[i]]/deg[f[i]]);
	s[f[f[i]]].insert(a[f[i]]);
	s[f[f[f[i]]]].erase(s[f[f[f[i]]]].find(a[f[f[i]]]));
	a[f[f[i]]]-=t[f[i]]/(deg[f[i]]+1);
	a[f[f[i]]]+=t[f[i]]/deg[f[i]];
	s[f[f[f[i]]]].insert(a[f[f[i]]]);
	deg[f[i]]--;
	deg[j]++;
	s[j].insert(a[i]);
	s[f[j]].erase(s[f[j]].find(a[j]));
	a[j]+=t[i]/(deg[i]+1);
	a[j]-=t[j]-(deg[j]-1)*(t[j]/deg[j]);
	a[j]+=t[j]-deg[j]*(t[j]/(deg[j]+1));
	s[f[j]].insert(a[j]);
	s[f[f[j]]].erase(s[f[f[j]]].find(a[f[j]]));
	a[f[j]]-=t[j]/deg[j];
	a[f[j]]+=t[j]/(deg[j]+1);
	s[f[f[j]]].insert(a[f[j]]);
	add(f[i]);
	add(f[f[i]]);
	add(f[f[f[i]]]);
	add(j);
	add(f[j]);
	add(f[f[j]]);
	f[i]=j;
}
int main(){
	read(n),read(q);
	for(int i=1;i<=n;i++){
		read(t[i]);
	}
	for(int i=1;i<=n;i++){
		read(f[i]);
	}
	for(int i=1;i<=n;i++){
		deg[i]++;
		deg[f[i]]++;
	}
	for(int i=1;i<=n;i++){
		a[i]+=t[i]-deg[i]*(t[i]/(deg[i]+1));
		a[f[i]]+=t[i]/(deg[i]+1);
	}
	for(int i=1;i<=n;i++){
		s[f[i]].insert(a[i]);
	}
	for(int i=1;i<=n;i++){
		add(i);
	}
	for(int i=1;i<=q;i++){
		int op;
		read(op);
		if(op==1){
			int x,y;
			read(x),read(y);
			work(x,y);
		}
		else if(op==2){
			int x;
			read(x);
			printf("%lld
",a[x]+t[f[x]]/(deg[f[x]]+1));
		}
		else{
			printf("%lld %lld
",(*s[0].begin()),(*(--s[0].end())));
		}
	}
	return 0;
}

本博客欢迎转载,转载请注明文章出处作者
原文地址:https://www.cnblogs.com/withhope/p/13552539.html