zoukankan      html  css  js  c++  java
  • luogu P2056 [ZJOI2007]捉迷藏 |动态点分治

    题目描述

    Jiajia 和 Wind 是一对恩爱的夫妻,并且他们有很多孩子。某天,Jiajia、Wind 和孩子们决定在家里玩捉迷藏游戏。他们的家很大且构造很奇特,由 NNN 个屋子和 N−1N-1N−1 条双向走廊组成,这 N−1N-1N−1 条走廊的分布使得任意两个屋子都互相可达。

    游戏是这样进行的,孩子们负责躲藏,Jiajia 负责找,而 Wind 负责操纵这 NNN 个屋子的灯。在起初的时候,所有的灯都没有被打开。每一次,孩子们只会躲藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要求打开某个房间的电灯或者关闭某个房间的电灯。为了评估某一次游戏的复杂性,Jiajia 希望知道可能的最远的两个孩子的距离(即最远的两个关灯房间的距离)。

    我们将以如下形式定义每一种操作:

    C(hange) i 改变第 iii 个房间的照明状态,若原来打开,则关闭;若原来关闭,则打开。
    G(ame) 开始一次游戏,查询最远的两个关灯房间的距离。
    

    输入格式

    第一行包含一个整数 NNN,表示房间的个数,房间将被编号为 1,2,3…N1,2,3…N1,2,3…N 的整数。

    接下来 N−1N-1N−1 行每行两个整数 aaa, bbb,表示房间 aaa 与房间 bbb 之间有一条走廊相连。

    接下来一行包含一个整数 QQQ,表示操作次数。接着 QQQ 行,每行一个操作,如上文所示。

    输出格式

    对于每一个操作 Game,输出一个非负整数,表示最远的两个关灯房间的距离。若只有一个房间是关着灯的,输出 0;若所有房间的灯都开着,输出 -1。


    #include<queue>
    #include<cstdio>
    #define inf 1000000000
    #define mod 1000000007
    #define pa pair<int,int>
    #define ll long long 
    using namespace std;
    inline int read(){
        int x=0;char ch=getchar();
        while(ch<'0'||ch>'9'){ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x;
    }
    int bin[20],Log[200005];
    int n,m,G,cnt,dfn,sum,tot;
    int size[100005],f[100005],deep[100005],last[100005];
    int mn[18][200005],pos[100005],fa[100005];
    bool vis[100005],clo[100005];
    struct edge{
    	int to,next;
    }e[200005];
    inline void insert(int u,int v){
    	e[++cnt]=(edge){v,last[u]};last[u]=cnt;
    	e[++cnt]=(edge){u,last[v]};last[v]=cnt;
    }
    struct heap{
    	priority_queue<int> A,B;
    	void push(int x){
    		A.push(x);
    	}
    	void erase(int x){
    		B.push(x);
    	}
    	void pop(){
    		while(B.size()&&A.top()==B.top())
    			A.pop(),B.pop();
    		A.pop();
    	}
    	int top(){
    		while(B.size()&&A.top()==B.top())
    			A.pop(),B.pop();
    		if(!A.size())return 0;
    		return A.top();
    	}
    	int size(){
    		return A.size()-B.size();
    	}
    	int stop(){
    		if(size()<2)return 0;
    		int x=top();pop();
    		int y=top();push(x);
    		return y;
    	}
    }A,B[100005],C[100005];
    inline void dfs(int x,int fa){
    	mn[0][++dfn]=deep[x];
    	pos[x]=dfn;
    	for(int i=last[x];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==fa)continue;
    		deep[v]=deep[x]+1;
    		dfs(v,x);
    		mn[0][++dfn]=deep[x];
    	}
    }
    inline void getrt(int x,int fa){
    	size[x]=1; f[x]=0;
    	for(int i=last[x];i;i=e[i].next){
    		int v=e[i].to;
    		if(v==fa||vis[v])continue;
    		getrt(v,x);
    		size[x]+=size[v];
    		f[x]=max(f[x],size[v]);
    	}
    	f[x]=max(f[x],sum-size[x]);
    	if(f[x]<f[G])G=x;
    }
    inline void divi(int x,int f){
    	fa[x]=f; vis[x]=1;
    	for(int i=last[x];i;i=e[i].next){
    		int v=e[i].to;
    		if(vis[v])continue;
    		sum=size[v]; G=0; getrt(v,x);
    		divi(G,x);
    	}
    }
    inline int rmq(int x,int y){
    	x=pos[x]; y=pos[y];
    	if(y<x)swap(x,y);
    	int t=Log[y-x+1];
    	return min(mn[t][x],mn[t][y-bin[t]+1]);
    }
    inline int dis(int x,int y){
    	return deep[x]+deep[y]-2*rmq(x,y);
    }
    inline void turn_off(int u,int v){
    	if(u==v){
    		B[u].push(0);
    		if(B[u].size()==2)A.push(B[u].top());
    	}
    	if(!fa[u])return;
    	int f=fa[u],D=dis(f,v),tmp=C[u].top();
    	C[u].push(D);
    	if(D>tmp){
    		int mx=B[f].top()+B[f].stop(),size=B[f].size();
    		if(tmp)B[f].erase(tmp);
    		B[f].push(D);
    		int now=B[f].top()+B[f].stop();
    		if(now>mx){
    			if(size>=2)A.erase(mx);
    			if(B[f].size()>=2)A.push(now);
    		}
    	}
    	turn_off(f,v);
    }
    inline void turn_on(int u,int v){
    	if(u==v){
    		if(B[u].size()==2)A.erase(B[u].top());
    		B[u].erase(0);
    	}
    	if(!fa[u])return;
    	int f=fa[u],D=dis(f,v),tmp=C[u].top();
    	C[u].erase(D);
    	if(D==tmp){
    		int mx=B[f].top()+B[f].stop(),size=B[f].size();
    		B[f].erase(D);
    		if(C[u].top())B[f].push(C[u].top());
    		int now=B[f].top()+B[f].stop();
    		if(now<mx){
    			if(size>=2)A.erase(mx);
    			if(B[f].size()>=2)A.push(now);
    		}
    	}
    	turn_on(f,v);
    }
    int main(){
    	register int i,j;
    	bin[0]=1; for(i=1;i<20;i++)bin[i]=bin[i-1]<<1;
    	Log[0]=-1; for(i=1;i<=200000;i++)Log[i]=Log[i>>1]+1;
    	n=read();
    	for(i=1;i<n;i++)insert(read(),read());
    	dfs(1,0);
    	for(i=1;i<=Log[dfn];i++) for(j=1;j<=dfn;j++)
    	mn[i][j]=min(mn[i-1][j],mn[i-1][j+bin[i-1]]);
    	G=0; f[0]=inf; sum=n;
    	getrt(1,0); divi(G,0);
    	for(i=1;i<=n;i++)C[i].push(0);
    	for(i=1;i<=n;i++)clo[i]=1;
    	for(i=1;i<=n;i++){
    		turn_off(i,i);
    		tot++;
    	}
    	char ch[2];
    	m=read();
    	while(m--){
    		scanf("%s",ch+1);
    		if(ch[1]=='G'){
    			if(tot<=1)printf("%d
    ",tot-1);
    			else printf("%d
    ",A.top());
    		}else {
    			int x=read();
    			if(clo[x])turn_on(x,x),tot--;
    			else turn_off(x,x),tot++;
    			clo[x]^=1;
    		}
    	}
    }
    
  • 相关阅读:
    ERROR: HHH000123: IllegalArgumentException in class: com.tt.hibernate.helloworld.News, setter method of property: date
    Tomcat服务器重启失败:The server may already be running in another process, or a system process may be using the port.
    ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'type=InnoDB' at line 7
    跨平台开发之阿里Weex框架环境搭建(一)
    fielderror里的fieldName代表的是jsp里的fieldName还是Action类的成员变量?(待解答)
    Virtualbox 安装
    下载CentOS镜像
    Express框架的创建
    安装MongoDB及所遇见的问题和解决方案
    javascript 插入DOM节点
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/12124252.html
Copyright © 2011-2022 走看看