题目大意

给一\(n\)(\(n\leq10^5\))个点的一棵树,每个点有可能是黑色或白色,一开始所有点都是黑色,支持以下两种操作:

1.改变一个点的颜色

2.询问最远的黑色点对的距离

题解

据说是动态点分治板板题

考虑点分治,发现容斥略有难想

所以考虑边分治,用可删堆维护重心边两侧到重心边最远的黑点到重心边的距离

代码
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
#define pb push_back
#define ls (u<<1)
#define rs (u<<1|1)
#define maxn 100010
#define maxnd (maxn<<1)
#define maxm (maxnd<<1)
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void write(int x)
{
if(x==0){putchar('0'),putchar('\n');return;}
int f=0;char ch[20];
if(x<0)putchar('-'),x=-x;
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
return;
}
int siz[maxnd],tot,n,fir[maxnd],nxt[maxm],v[maxm],cntrd,m,d[20][maxn],maxd[maxnd<<2];
int sumsiz,wt,minsiz,w[maxm],vis[maxm],lens[maxn],wtk[maxnd<<2],bacn[maxn],stat[maxn];
vector<int>to[maxn];
struct deq
{
priority_queue<int >yes,no;
void push(int x){yes.push(x);}
void del(int x){no.push(x);}
int top(){while(!no.empty()&&yes.top()==no.top())yes.pop(),no.pop();return yes.top();}
int size(){return yes.size()-no.size();}
}q[maxnd<<2];
void ade(int u1,int v1,int w1){v[cntrd]=v1,nxt[cntrd]=fir[u1],w[cntrd]=w1,fir[u1]=cntrd++;}
void get2(int u,int fa)
{
int lim=to[u].size()-1,lst=u,f=0;
rep(i,0,lim)if(to[u][i]!=fa)
{
if(f){tot++,ade(lst,tot,0),ade(tot,lst,0),lst=tot;}
ade(lst,to[u][i],1),ade(to[u][i],lst,1);f=1;
}
rep(i,0,lim)if(to[u][i]!=fa)get2(to[u][i],u);
}
void getsiz(int u,int fa)
{
siz[u]=1;
view(u,k)if(v[k]!=fa&&!vis[k])
{
getsiz(v[k],u),siz[u]+=siz[v[k]];
int nowmax=max(sumsiz-siz[v[k]],siz[v[k]]);
if(nowmax<minsiz)wt=k,minsiz=nowmax;
}
}
void getdis(int u,int fa,int pos,int len,int dis)
{
if(u<=n){d[len][u]=dis,q[pos].push(dis);}
view(u,k)if(!vis[k]&&v[k]!=fa){getdis(v[k],u,pos,len,dis+w[k]);}
}
void pu(int u)
{
maxd[u]=-1;
if(q[ls].size()&&q[rs].size()){maxd[u]=q[ls].top()+q[rs].top()+w[wtk[u]];}
maxd[u]=max(maxd[u],max(maxd[ls],maxd[rs]));
}
void getwt(int u,int nd,int nowsiz,int len)
{
if(nowsiz==1){maxd[u]=-1;if(nd<=n)lens[nd]=len,bacn[nd]=u;return;}
sumsiz=nowsiz,minsiz=tot+1,wt=-1,getsiz(nd,0);int uu=v[wt],vv=v[wt^1],su=siz[uu]>siz[vv]?nowsiz-siz[vv]:siz[uu],sv=siz[vv]>siz[uu]?nowsiz-siz[uu]:siz[vv];
vis[wt]=vis[wt^1]=1;wtk[u]=wt;
getdis(uu,0,ls,len,0),getdis(vv,0,rs,len,0);
getwt(ls,uu,su,len+1),getwt(rs,vv,sv,len+1);
pu(u);
}
char S[5];
void chg(int x)
{
int u=bacn[x],len=lens[x],fa=u>>1;
while(fa)
{
if(stat[x])q[u].push(d[len-1][x]);
else q[u].del(d[len-1][x]);
pu(fa);
u>>=1,len--,fa=(u>>1);
}stat[x]^=1;
}
int main()
{
n=read();memset(fir,-1,sizeof(fir));tot=n;
rep(i,1,n-1){int x=read(),y=read();to[x].pb(y),to[y].pb(x);}
get2(1,0),getwt(1,1,tot,0);
m=read();
while(m--)
{
int x;
scanf("%s",S);
if(S[0]=='C'){x=read();chg(x);}
else write(maxd[1]);
}
return 0;
}
一些感想

时隔一年,终于正式切了 (之前是照着题解敲) 这道题

相比于去年,我这个弱智猎人还是有一些进步的,至少也得是弱智猎人G

祝我在明天的紧急任务中狩猎愉快!

并不对劲的bzoj1095:p2056:[ZJOI2007]捉迷藏的更多相关文章

  1. 洛谷 P2056 [ZJOI2007]捉迷藏 解题报告

    P2056 [ZJOI2007]捉迷藏 题目描述 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏.他们的家很大且构造很奇特,由\ ...

  2. 【bzoj1095】 ZJOI2007—捉迷藏

    http://www.lydsy.com/JudgeOnline/problem.php?id=1095 (题目链接) 题意 一棵树,求最远的两黑点之间的距离,每次可以将黑点染白或者将白点染黑. So ...

  3. 洛谷 P2056 [ZJOI2007]捉迷藏 题解【点分治】【堆】【图论】

    动态点分治入 门 题? 题目描述 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏.他们的家很大且构造很奇特,由 \(N\) 个屋 ...

  4. 洛谷 P2056 [ZJOI2007]捉迷藏 || bzoj 1095: [ZJOI2007]Hide 捉迷藏 || 洛谷 P4115 Qtree4 || SP2666 QTREE4 - Query on a tree IV

    意识到一点:在进行点分治时,每一个点都会作为某一级重心出现,且任意一点只作为重心恰好一次.因此原树上任意一个节点都会出现在点分树上,且是恰好一次 https://www.cnblogs.com/zzq ...

  5. Luogu P2056 [ZJOI2007]捉迷藏

    入坑动态点分治的题目,感觉还不错被卡常后重构代码 首先静态点分治相信大家肯定都会,就是不断找重心然后暴力计算每棵子树内的贡献. 这题如果只有单次询问,我们很容易想到对于每个分治中心的所以儿子的子树中找 ...

  6. P2056 [ZJOI2007]捉迷藏

    传送门 如果没有修改显然就直接点分治 有修改那就动态点分治 动态点分治就是在点分树上维护一些东西,查询时也在点分树上查 因为点分树深度是$log$的所以可以保证时间复杂度 此题我们需要在点分树上维护 ...

  7. [洛谷P2056][ZJOI2007]捉迷藏(2019-7-20考试)

    题目大意:有一棵$n(n\leqslant10^6)$个点的树,上面所有点是黑点,有$m$次操作: $C\;u$:把点$u$颜色翻转 $G$:问树上最远的两个黑点的距离,若没有黑点输出$0$ 题解:有 ...

  8. 【BZOJ1095】[ZJOI2007]Hide 捉迷藏 动态树分治+堆

    [BZOJ1095][ZJOI2007]Hide 捉迷藏 Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉 ...

  9. 树上最长链 Farthest Nodes in a Tree LightOJ - 1094 && [ZJOI2007]捉迷藏 && 最长链

    树上最远点对(树的直径) 做法1:树形dp 最长路一定是经过树上的某一个节点的. 因此: an1[i],an2[i]分别表示一个点向下的最长链和次长链,次长链不存在就设为0:这两者很容易求 an3[i ...

随机推荐

  1. weblogic运维时经常遇到的问题和常用的配置

      希望这篇能把weblogic运维时经常遇到的问题.常用的配置汇总到一起. 1.配置jvm参数: 一般在domain启动过程中会看到以下启动的日志信息,如下图所示: 图中红色方框部分为启动weblo ...

  2. iOS -- SKTransition类

      SKTransition类 继承自 NSObject 符合 NSObject(NSObject) 框架  /System/Library/Frameworks/SpriteKit.framewor ...

  3. GOPATH设置

    go help gopath查看gopath的原文帮助信息 go env查看gopath的配置 GOPATH与工作空间 前面我们在安装Go的时候看到需要设置GOPATH变量,Go从1.1版本到1.7必 ...

  4. Shadow Map阴影贴图技术之探 【转】

    这两天勉勉强强把一个shadowmap的demo做出来了.参考资料多,苦头可不少.Shadow Map技术是目前与Shadow Volume技术并行的传统阴影渲染技术,而且在游戏领域可谓占很大优势.本 ...

  5. [转载] C/C++中怎样获取日期和时间

    C/C++中怎样获取日期和时间摘要:  本文从介绍基础概念入手,探讨了在C/C++中对日期和时间操作所用到的数据结构和函数,并对计时.时间的获取.时间的计算和显示格式等方面进行了阐述.本文还通过大量的 ...

  6. js 字符串常用方法

    数组方面 1.push:向数组尾部增加内容,返回的是新数组的长度. var arr = [1,2,3]; console.log(arr); var b = arr.push(4); console. ...

  7. com关于IUnknown接口

    com定义的每个接口都必须从IUnknown继承过来,主要原因是IUnknown接口提供了两个很重要的特性:生存期控制和接口查询. 客户程序仅仅能通过接口与com对象进行通信.尽管客户程序能够无论对象 ...

  8. 笔记04 WPF的Binding

    oneWay:使用 OneWay 绑定时,每当源发生变化,数据就会从源流向目标. OneTime: 绑定也会将数据从源发送到目标:但是,仅当启动了应用程序或 DataContext 发生更改时才会如此 ...

  9. 使用Pig对手机上网日志进行分析

    在安装成功Pig的基础上.本文将使用Pig对手机上网日志进行分析,详细过程例如以下: 写在前面: 手机上网日志文件phone_log.txt.文件内容 及 字段说明部分截图例如以下 需求分析 显示每一 ...

  10. SpringSecurity学习笔记(一):搭建最简单的SpringSecurity应用

    学习过程参考自:http://www.mossle.com/docs/auth/html/pt01-quickstart.html 一.搭建Maven项目: 所需引用的jar包如下: pom.xml文 ...