zoukankan      html  css  js  c++  java
  • 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;
    }
    
    
    本博客欢迎转载,转载请注明文章出处作者
  • 相关阅读:
    包含min函数的栈
    栈的应用
    给定金额m和红包数量n
    顺时针打印矩阵
    二叉树的镜像
    elementUI table表头错位问题
    金额格式化
    ajax跨域问题全解
    JavaScript 的 this 原理
    vue技术分享-你可能不知道的7个秘密
  • 原文地址:https://www.cnblogs.com/withhope/p/13552539.html
Copyright © 2011-2022 走看看