zoukankan      html  css  js  c++  java
  • 【刷题】BZOJ 1095 [ZJOI2007]Hide 捉迷藏

    Description

      捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子。某天,Jiajia、Wind和孩子们决定在家里玩
    捉迷藏游戏。他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋
    子都互相可达。游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯。在起初的
    时候,所有的灯都没有被打开。每一次,孩子们只会躲藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要
    求打开某个房间的电灯或者关闭某个房间的电灯。为了评估某一次游戏的复杂性,Jiajia希望知道可能的最远的两
    个孩子的距离(即最远的两个关灯房间的距离)。 我们将以如下形式定义每一种操作: C(hange) i 改变第i个房
    间的照明状态,若原来打开,则关闭;若原来关闭,则打开。 G(ame) 开始一次游戏,查询最远的两个关灯房间的
    距离。

    Input

      第一行包含一个整数N,表示房间的个数,房间将被编号为1,2,3…N的整数。接下来N-1行每行两个整数a, b,
    表示房间a与房间b之间有一条走廊相连。接下来一行包含一个整数Q,表示操作次数。接着Q行,每行一个操作,如
    上文所示。

    Output

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

    Sample Input

    8
    1 2
    2 3
    3 4
    3 5
    3 6
    6 7
    6 8
    7
    G
    C 1
    G
    C 2
    G
    C 1
    G

    Sample Output

    4
    3
    3
    4

    HINT

    对于100%的数据, N ≤100000, M ≤500000。

    Solution

    线段树维护直径
    第一反应就是线段树,感觉动态点分和括号序列太繁琐了
    树剖后用线段树搞就好了,修改也很方便
    线段树维护直径基于这样一条性质:两棵树合并,新的直径的两个端点一定是原两棵树直径四个端点之二
    具体可以看这里

    #include<bits/stdc++.h>
    #define ui unsigned int
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    const int MAXN=100000+10;
    int n,m,e,beg[MAXN],nex[MAXN<<1],to[MAXN<<1],Mn[22][MAXN<<2],dep[MAXN],st[MAXN],ed[MAXN],cnt,hson[MAXN],size[MAXN],bcnt,black[5],lst[MAXN],ap[MAXN],lg[MAXN<<2],tot,fa[MAXN];
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char ch='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(ch!='')putchar(ch);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    inline void insert(int x,int y)
    {
    	to[++e]=y;
    	nex[e]=beg[x];
    	beg[x]=e;
    }
    inline void dfs1(int x,int f)
    {
    	int res=0;
    	Mn[0][ap[x]=++tot]=x;
    	dep[x]=dep[f]+1;size[x]=1;fa[x]=f;
    	for(register int i=beg[x];i;i=nex[i])
    	{
    		if(to[i]!=f)
    		{
    			dfs1(to[i],x);
    			size[x]+=size[to[i]];
    			if(size[to[i]]>res)res=size[to[i]],hson[x]=to[i];
    		}
    		Mn[0][++tot]=x;
    	}
    }
    inline void dfs2(int x,int tp)
    {
    	st[x]=++cnt;lst[cnt]=x;
    	if(hson[x])dfs2(hson[x],tp);
    	for(register int i=beg[x];i;i=nex[i])
    		if(to[i]==fa[x]||to[i]==hson[x])continue;
    		else dfs2(to[i],to[i]);
    	ed[x]=cnt;
    }
    inline int LCA(int u,int v)
    {
    	int l=ap[u],r=ap[v];
    	if(l>r)std::swap(l,r);
    	int k=lg[r-l+1];
    	return dep[Mn[k][l]]<dep[Mn[k][r-(1<<k)+1]]?Mn[k][l]:Mn[k][r-(1<<k)+1];
    }
    inline int dist(int u,int v)
    {
    	return dep[u]+dep[v]-(dep[LCA(u,v)]<<1);
    }
    inline std::pair<int,int> find()
    {
    	int res=-1;
    	std::pair<int,int> ps;
    	std::sort(black,black+bcnt+1);
    	bcnt=std::unique(black,black+bcnt+1)-black-1;
    	for(register int i=1;i<=bcnt;++i)
    		for(register int j=i,now;j<=bcnt;++j)
    		{
    			now=dist(black[i],black[j]);
    			if(now>res)res=now,ps=std::make_pair(black[i],black[j]);
    		}
    	return ps;
    }
    #define Mid ((l+r)>>1)
    #define ls rt<<1
    #define rs rt<<1|1
    #define lson ls,l,Mid
    #define rson rs,Mid+1,r
    #define ft first
    #define sd second
    struct Segment_Tree{
    	std::pair<int,int> pnt[MAXN<<2];
    	int col[MAXN<<2];
    	inline std::pair<int,int> Merge(std::pair<int,int> lp,std::pair<int,int> rp)
    	{
    		bcnt=0;
    		if(lp.ft&&col[lp.ft])black[++bcnt]=lp.ft;
    		if(lp.sd&&col[lp.sd])black[++bcnt]=lp.sd;
    		if(rp.ft&&col[rp.ft])black[++bcnt]=rp.ft;
    		if(rp.sd&&col[rp.sd])black[++bcnt]=rp.sd;
    		if(!bcnt)return std::make_pair(0,0);
    		else return find();
    	}
    	inline void Build(int rt,int l,int r)
    	{
    		if(l==r)pnt[rt]=std::make_pair(lst[l],lst[r]),col[lst[l]]=1;
    		else Build(lson),Build(rson),pnt[rt]=Merge(pnt[ls],pnt[rs]);
    	}
    	inline void Update(int rt,int l,int r,int ps)
    	{
    		if(l==r&&r==ps)
    		{
    			col[lst[l]]^=1;
    			if(col[lst[l]])pnt[rt]=std::make_pair(lst[l],lst[r]);
    			else pnt[rt]=std::make_pair(0,0);
    		}
    		else
    		{
    			if(ps<=Mid)Update(lson,ps);
    			else Update(rson,ps);
    			pnt[rt]=Merge(pnt[ls],pnt[rs]);
    		}
    	}
    	inline std::pair<int,int> Query(int rt,int l,int r,int L,int R)
    	{
    		if(L==l&&r==R)return pnt[rt];
    		else
    		{
    			if(R<=Mid)return Query(lson,L,R);
    			else if(L>Mid)Query(rson,L,R);
    			else return Merge(Query(lson,L,Mid),Query(rson,Mid+1,R));
    		}
    	}
    };
    Segment_Tree T;
    #undef Mid
    #undef ls
    #undef rs
    #undef lson
    #undef rson
    #undef ft
    #undef sd
    inline void init()
    {
    	dfs1(1,0);dfs2(1,1);
    	for(register int i=2;i<=tot;++i)lg[i]=lg[i>>1]+1;
    	for(register int j=1;j<=lg[tot];++j)
    		for(register int i=1;i+(1<<j)<=tot;++i)Mn[j][i]=dep[Mn[j-1][i]]<dep[Mn[j-1][i+(1<<j-1)]]?Mn[j-1][i]:Mn[j-1][i+(1<<j-1)];
    	T.Build(1,1,n);
    }
    int main()
    {
    	read(n);
    	for(register int i=1;i<n;++i)
    	{
    		int u,v;read(u);read(v);
    		insert(u,v);insert(v,u);
    	}
    	init();
    	read(m);
    	while(m--)
    	{
    		char opt[1];scanf("%s",opt);
    		if(opt[0]=='G')
    		{
    			std::pair<int,int> ans=T.Query(1,1,n,st[1],ed[1]);
    			if(!ans.first)puts("-1");
    			else write(dist(ans.first,ans.second),'
    ');
    		}
    		if(opt[0]=='C')
    		{
    			int x;read(x);
    			T.Update(1,1,n,st[x]);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    斯坦福CS231n—深度学习与计算机视觉----学习笔记 课时10
    斯坦福CS231n—深度学习与计算机视觉----学习笔记 课时8&&9
    斯坦福CS231n—深度学习与计算机视觉----学习笔记 课时7
    斯坦福CS231n—深度学习与计算机视觉----学习笔记 课时6
    sprintf()函数用法
    openssl生成签名与验证签名
    PHP_EOL换行 与 base64编码
    grep配置颜色显示
    curl发送json格式数据
    sublime text3作为php开发IDE
  • 原文地址:https://www.cnblogs.com/hongyj/p/9301834.html
Copyright © 2011-2022 走看看