题目大意

给一\(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. apache一个IP绑定多个域名

    用ServerAlias <VirtualHost *:80>ServerAdmin i@kuigg.comDocumentRoot /www/kuigg.comServerName ku ...

  2. 网站无法显示logo?

    那是因为你没有配置favicon.ico,每个网站根目录都会有一个favicon.ico,因为每个服务器都会请求根目录下的它.

  3. SASS入门之SASS安装

    当然...凭借我这样的肤浅的智商,根本不能理解什么叫certificate verfiy fail... 所以找了一段时间的方法,最后最终在一个sass群里找到了... 发在这里纯属作为自己的一个学习 ...

  4. windows程序设计——飞机大战笔记(Access数据库的使用)

    //////////////////2015/07/22/////////////////// /////////////////by xbw ///////////////////////// // ...

  5. 关于ASP.NET MVC中Response.Redirect和RedirectToAction的BUG (跳转后继续执行后面代码而不结束进程)以及处理方法

    关于ASP.NET MVC中Response.Redirect和RedirectToAction的BUG (跳转后继续执行后面代码而不结束进程)以及处理方法   在传统的ASP.NET中,使用Resp ...

  6. GTK入门学习:布局练习之计算器

    接下来,我们做一个布局练习.例如以下图: 我们用表格布局实现,表格布局參考坐标例如以下: 这里我们用到行编辑控件( GtkEntry ). 行编辑的创建: GtkWidget * gtk_entry_ ...

  7. 【Sprint3冲刺之前】敏捷团队绩效考核(刘铸辉)

     TD学生助手团队已经在4.22~4.30完成了为期9天的Sprint2计划,并在Sprint2总结会议中安排了五一放假每个人的任务分配,下面发布下Sprint2冲刺周期的阶段性成果. Sprint2 ...

  8. mini2440使用jlink烧写superboot到norflash

    Jlink版本号:J-flash ARM V4.12                    J-Flash ARM的配置. 一般说来file-->open project里面会找到一些*.jfl ...

  9. 设置Ubuntu 16.04 LTS的Unity启动器的位置命令

    将Ubuntu 16.04 LTS的Unity启动器移动到桌面底部命令:gsettings set com.canonical.Unity.Launcher launcher-position Bot ...

  10. uboot 命令

    1.清除前一次的编译结果: make distclean 2.配置makefile:选择开发板 make  smdk6410_config 3.编译 make 注意::编译时,打开的文档文件,目录都要 ...