题目大意

给一\(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

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

最新文章

  1. 重写ViewPager方法,防止滑动广告尾页的时候,Fragment也改变! (如果广告设置为轮播的话,不需要重写ViewPager)
  2. Python 学习之进制与编码
  3. C#删除文件和文件夹到回收站
  4. css3制作六边形图片
  5. ASP.NET缓存 Cache之数据缓存
  6. eclipse 最全快捷键(网络收集)
  7. 查看nginx编译安装
  8. Network boot from AMD Am79C970A
  9. 开源一个监控数据采集Agent:OpenFalcon-SuitAgent
  10. 1005 - Rooks(规律)
  11. 黄聪:Microsoft Enterprise Library 5.0 系列教程(六) Security Application Block
  12. easyui datagrid分页
  13. webpack常见的配置总结 ---只是一些常见的配置
  14. 【SqlServer系列】表达式(expression)
  15. centos7.4卸载再安装mariadb服务无法启动问题
  16. IDEA的校园邮箱激活方式
  17. 重识linux-linux的账号与用户组
  18. opencv学习笔记之cvSobel 函数解析
  19. js常用的几个验证
  20. MSSQL 错误:在将 varchar 值 &#39;1,2,3,5,6&#39; 转换成数据类型 int 时失败。

热门文章

  1. 定时任务crontab如何实现每秒执行?
  2. angular - 新建项目 - 2
  3. S3C2440 IIS操作 uda134x录放音
  4. Solaris 下解决上网问题以及远程登录问题
  5. UIView 的 autoresizingMask 属性 详解。
  6. linux系列之-—04 自动删除n天前日志【转】
  7. C# 利用ICSharpCode.SharpZipLib实现在线加密压缩和解密解压缩 C# 文件压缩加解密
  8. selenium之 chromedriver与chrome版本映射表(更新至v2.29)
  9. some cmds,tools and utils man
  10. vim调试