zoukankan      html  css  js  c++  java
  • LOJ#2230. 「BJOI2014」大融合

    LOJ#2230. 「BJOI2014」大融合

    题目描述

    小强要在$N$个孤立的星球上建立起一套通信系统。这套通信系统就是连接$N$个点的一个树。这个树的边是一条一条添加上去的。

    在某个时刻,一条边的负载就是它所在的当前能够联通的树上路过它的简单路径的数量。

    例如,在上图中,现在一共有五条边。其中,$(3,8)$这条边的负载是$6$,因为有六条简单路径$2-3-8, 2-3-8-7, 3-8, 3-8-7, 4-3-8, 4-3-8-7$路过了$(3,8)$。

    现在,你的任务就是随着边的添加,动态的回答小强对于某些边的负载的询问。

    输入格式

    第一行包含两个整数$N,Q$,表示星球的数量和操作的数量。星球从$1$开始编号。

    接下来的$Q$行,每行是如下两种格式之一:

    A x y 表示在$x$和$y$之间连一条边。保证之前$x$和$y$是不联通的。
    Q x y 表示询问$(x,y)$这条边上的负载。保证$x$和$y$之间有一条边。

    输出格式

    对每个查询操作,输出被查询的边的负载。

    样例

    样例输入

    8 6
    A 2 3
    A 3 4
    A 3 8
    A 8 7
    A 6 5
    Q 3 8

    样例输出

    6

    数据范围与提示

    对于所有数据,$1 leq N,Q leq 100000$。


    题解Here!

    $LCT$大法好!

    维护虚树中每个节点的虚子节点个数。

    连边时注意:不是$makeroot$,是$split$。(坑了我好久。。。)

    还有$access$时维护一下即可。

    最后答案就是:

    $$ ext{x的虚子节点个数} imes( ext{y的虚子节点个数}- ext{x的虚子节点个数})$$

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define MAXN 100010
    using namespace std;
    int n,m;
    struct node{
    	int f,v,s,flag,son[2];
    }a[MAXN];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline bool isroot(int rt){
    	return a[a[rt].f].son[0]!=rt&&a[a[rt].f].son[1]!=rt;
    }
    inline void pushup(int rt){
    	if(!rt)return;
    	a[rt].s=a[a[rt].son[0]].s+a[a[rt].son[1]].s+a[rt].v+1;
    }
    inline void pushdown(int rt){
    	if(!rt||!a[rt].flag)return;
    	a[a[rt].son[0]].flag^=1;a[a[rt].son[1]].flag^=1;a[rt].flag^=1;
    	swap(a[rt].son[0],a[rt].son[1]);
    }
    inline void turn(int rt){
    	int x=a[rt].f,y=a[x].f,k=a[x].son[0]==rt?1:0;
    	if(!isroot(x)){
    		if(a[y].son[0]==x)a[y].son[0]=rt;
    		else a[y].son[1]=rt;
    	}
    	a[rt].f=y;a[x].f=rt;a[a[rt].son[k]].f=x;
    	a[x].son[k^1]=a[rt].son[k];a[rt].son[k]=x;
    	pushup(x);pushup(rt);
    }
    void splay(int rt){
    	int top=0,stack[MAXN];
    	stack[++top]=rt;
    	for(int i=rt;!isroot(i);i=a[i].f)stack[++top]=a[i].f;
    	while(top)pushdown(stack[top--]);
    	while(!isroot(rt)){
    		int x=a[rt].f,y=a[x].f;
    		if(!isroot(x)){
    			if((a[y].son[0]==x)^(a[x].son[0]==rt))turn(rt);
    			else turn(x);
    		}
    		turn(rt);
    	}
    }
    void access(int rt){
    	for(int i=0;rt;i=rt,rt=a[rt].f){
    		splay(rt);
    		a[rt].v+=a[a[rt].son[1]].s-a[i].s;
    		a[rt].son[1]=i;
    		pushup(rt);
    	}
    }
    inline void makeroot(int rt){access(rt);splay(rt);a[rt].flag^=1;}
    inline void split(int x,int y){makeroot(x);access(y);splay(y);}
    inline void link(int x,int y){
        split(x,y);
    	a[x].f=y;
        a[y].v+=a[x].s;
        pushup(y);
    }
    void work(){
    	char ch[2];
    	int x,y;
    	n=read();m=read();
    	for(int i=1;i<=n;i++)a[i].s=1;
    	while(m--){
    		scanf("%s",ch);x=read();y=read();
    		if(ch[0]=='A')link(x,y);
    		if(ch[0]=='Q'){
    			split(x,y);
    			printf("%lld
    ",(long long)a[x].s*(a[y].s-a[x].s));
    		}
    	}
    }
    int main(){
    	work(); 
    	return 0;
    }
    
  • 相关阅读:
    javascript 操作 excel 全攻略
    ASP.NET中上传并读取Excel文件数据
    创意无限!一组网页边栏过渡动画【附源码下载】
    jQuery一些常用特效方法使用实例
    jQuery的deferred对象详解
    Jquery 数组操作
    10 款精美的 CSS3 全新特效
    20 个用于处理页面滚动效果的 jQuery 插件
    Linux-exec命令试验驱动(12)
    动态规划-数正方形(详解)
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9940964.html
Copyright © 2011-2022 走看看