树分治,对于每个分治结构,维护两棵线段树。

第一棵按dfs序维护所有点到重心的距离,第二棵维护每个分支的最长链。

那么当前结构对答案的贡献就是第二棵线段树的最大值$+$次大值。

对于操作$0$,如果是激活某个点,则直接把它距离$+=inf$,隐藏某个点则是$-=inf$。

对于操作$1$,相当于子树全部加上一个值,进行区间加即可。

时间复杂度$O(n\log^2n)$。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100010,M=262150,inf=1000000000;
int n,m,i,j,e[N][3],ex[N],active,q[N][3],ans[N],tag[M];
int g[N],v[N<<1],w[N<<1],ok[N<<1],nxt[N<<1],ed,G[N],NXT[N];
int son[N],f[N],all,now;
inline void read(int&a){
char c;bool f=0;a=0;
while(!((((c=getchar())>='0')&&(c<='9'))||(c=='-')));
if(c!='-')a=c-'0';else f=1;
while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';
if(f)a=-a;
}
inline void umax(int&a,int b){if(a<b)a=b;}
void build(int x,int a,int b){
tag[x]=-inf;
if(a==b)return;
int mid=(a+b)>>1;
build(x<<1,a,mid),build(x<<1|1,mid+1,b);
}
void change(int x,int a,int b,int c,int d,int p){
if(c<=a&&b<=d){umax(tag[x],p);return;}
int mid=(a+b)>>1;
if(c<=mid)change(x<<1,a,mid,c,d,p);
if(d>mid)change(x<<1|1,mid+1,b,c,d,p);
}
void print(int x,int a,int b){
if(a==b){
if(q[a][0]==2){
if(ans[a]==1)puts("Nothing..Nothing!");
else if(ans[a]==2)puts("Only one baby!");
else printf("%d\n",tag[x]);
}
return;
}
int mid=(a+b)>>1;
umax(tag[x<<1],tag[x]);
umax(tag[x<<1|1],tag[x]);
print(x<<1,a,mid),print(x<<1|1,mid+1,b);
}
inline void add(int x,int y,int z){v[++ed]=y;w[ed]=z;ok[ed]=1;nxt[ed]=g[x];g[x]=ed;}
inline void ADD(int x,int y){NXT[y]=G[x];G[x]=y;}
void findroot(int x,int y){
son[x]=1;f[x]=0;
for(int i=g[x];i;i=nxt[i])if(ok[i]&&v[i]!=y){
findroot(v[i],x);
son[x]+=son[v[i]];
if(son[v[i]]>f[x])f[x]=son[v[i]];
}
if(all-son[x]>f[x])f[x]=all-son[x];
if(f[x]<f[now])now=x;
}
int tmp,cur,edge[N],from[N],vis[N];
int d[N],st[N],en[N],dfn,ST[N],EN[N],cp,pool[N];
namespace Node{
int q[N],v[M],tag[M];
inline void tag1(int x,int p){v[x]+=p;tag[x]+=p;}
inline void pb(int x){if(tag[x])tag1(x<<1,tag[x]),tag1(x<<1|1,tag[x]),tag[x]=0;}
inline void up(int x){v[x]=max(v[x<<1],v[x<<1|1]);}
void build(int x,int a,int b){
tag[x]=0;
if(a==b){v[x]=q[a];return;}
int mid=(a+b)>>1;
build(x<<1,a,mid),build(x<<1|1,mid+1,b),up(x);
}
void add(int x,int a,int b,int c,int d,int p){
if(c<=a&&b<=d){tag1(x,p);return;}
pb(x);
int mid=(a+b)>>1;
if(c<=mid)add(x<<1,a,mid,c,d,p);
if(d>mid)add(x<<1|1,mid+1,b,c,d,p);
up(x);
}
int ask(int x,int a,int b,int c,int d){
if(c<=a&&b<=d)return v[x];
pb(x);
int mid=(a+b)>>1,t=-inf;
if(c<=mid)t=ask(x<<1,a,mid,c,d);
if(d>mid)umax(t,ask(x<<1|1,mid+1,b,c,d));
up(x);
return t;
}
}
namespace Sub{
int q[N],fir[M],sec[M];
inline void up(int x){
if(fir[x<<1]>fir[x<<1|1]){
fir[x]=fir[x<<1];
sec[x]=max(sec[x<<1],fir[x<<1|1]);
}else{
fir[x]=fir[x<<1|1];
sec[x]=max(fir[x<<1],sec[x<<1|1]);
}
}
void build(int x,int a,int b){
if(a==b){fir[x]=q[a];sec[x]=-inf;return;}
int mid=(a+b)>>1;
build(x<<1,a,mid),build(x<<1|1,mid+1,b),up(x);
}
void change(int x,int a,int b,int c,int p){
if(a==b){fir[x]=p;return;}
int mid=(a+b)>>1;
if(c<=mid)change(x<<1,a,mid,c,p);else change(x<<1|1,mid+1,b,c,p);
up(x);
}
}
inline void init(int x){
from[x]=cur;
vis[x]=now;
ex[x]=1;
for(int i=G[x];i;i=NXT[i])pool[++cp]=i;
}
void dfs(int x,int y,int z,int dep){
umax(tmp,z);
d[x]=dep;
st[x]=++dfn;
Node::q[dfn]=z;
init(x);
for(int i=g[x];i;i=nxt[i])if(ok[i]&&v[i]!=y)edge[i>>1]=w[i],dfs(v[i],x,z+w[i],dep+1);
en[x]=dfn;
}
inline void update(int l,int r){
if(l>r)return;
int t=Sub::sec[1];
if(ex[now])umax(t,0);
change(1,1,m,l,r,Sub::fir[1]+t);
}
void solve(int x){
int i;
cur=cp=dfn=d[x]=0;
init(x);
for(i=g[x];i;i=nxt[i])if(ok[i]){
edge[i>>1]=w[i];
cur++;
tmp=-inf;
ST[cur]=dfn+1;
dfs(v[i],x,w[i],1);
EN[cur]=dfn;
Sub::q[cur]=tmp;
}
if(!cur)return;
Node::build(1,1,dfn);
Sub::build(1,1,cur);
sort(pool+1,pool+cp+1);
pool[cp+1]=m+1;
update(1,pool[1]-1);
for(i=1;i<=cp;i++){
int A=q[pool[i]][0],B=q[pool[i]][1],C=q[pool[i]][2];
if(!A){
if(B==now){
ex[now]^=1;
update(pool[i],pool[i+1]-1);
continue;
}
if(ex[B])Node::add(1,1,dfn,st[B],st[B],-inf);
else Node::add(1,1,dfn,st[B],st[B],inf);
Sub::change(1,1,cur,from[B],Node::ask(1,1,dfn,ST[from[B]],EN[from[B]]));
ex[B]^=1;
}else{
if(vis[e[B][0]]!=now||vis[e[B][1]]!=now){
update(pool[i],pool[i+1]-1);
continue;
}
int z=d[e[B][0]]>d[e[B][1]]?e[B][0]:e[B][1];
Node::add(1,1,dfn,st[z],en[z],C-=edge[B]);
Sub::change(1,1,cur,from[z],Node::ask(1,1,dfn,ST[from[z]],EN[from[z]]));
edge[B]+=C;
}
update(pool[i],pool[i+1]-1);
}
for(i=g[x];i;i=nxt[i])if(ok[i]){
ok[i^1]=0;
f[0]=all=son[v[i]];
findroot(v[i],now=0);
solve(now);
}
}
int main(){
read(n);
for(ed=i=1;i<n;i++){
for(j=0;j<3;j++)read(e[i][j]);
add(e[i][0],e[i][1],e[i][2]);
add(e[i][1],e[i][0],e[i][2]);
}
read(m);
for(i=1;i<=n;i++)ex[i]=1;
for(active=n,i=1;i<=m;i++){
read(q[i][0]);
if(q[i][0]<2)read(q[i][1]);
if(q[i][0]==1)read(q[i][2]);
if(!q[i][0]){
if(ex[q[i][1]])active--;else active++;
ex[q[i][1]]^=1;
ADD(q[i][1],i);
}
if(q[i][0]==1)ADD(e[q[i][1]][0],i);
if(q[i][0]==2){
if(active==0)ans[i]=1;
if(active==1)ans[i]=2;
}
}
build(1,1,m);
f[0]=all=n;findroot(1,now=0);solve(now);
print(1,1,m);
return 0;
}

  

BZOJ1841 : 蚂蚁搬家的更多相关文章

  1. 计蒜客模拟赛5 D2T2 蚂蚁搬家

    很久很久以前,有很多蚂蚁部落共同生活在一片祥和的村庄里.但在某一天,村庄里突然出现了一只食蚁兽,蚂蚁们为了保全性命而决定搬家. 然而这个村庄四面环山,想要离开这个村庄必须要从地洞里离开,村子里一共有 ...

  2. 蚂蚁的难题(二)首尾相连数组的最大子数组和(DP)

    蚂蚁的难题(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 下雨了,下雨了,蚂蚁搬家了. 已知有n种食材需要搬走,这些食材从1到n依次排成了一个圈.小蚂蚁对每种食材 ...

  3. NYOJ 745 蚂蚁问题(两)

    蚂蚁的难题(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描写叙述 下雨了,下雨了.蚂蚁搬家了. 已知有n种食材须要搬走,这些食材从1到n依次排成了一个圈.小蚂蚁对每种 ...

  4. NYOJ 745 蚂蚁的难题(二)

    蚂蚁的难题(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 下雨了,下雨了,蚂蚁搬家了. 已知有n种食材需要搬走,这些食材从1到n依次排成了一个圈.小蚂蚁对每种 ...

  5. Burndown chart

    S型的燃尽图 在一次milestone开发过程中,开发者会持续编辑issue列表,每个issue都有自己的生命周期.燃尽图预期这些issues会被线性的消灭掉,所以从第一天直接到最后一天画个直线表示预 ...

  6. DevExpress 学习使用之 NavBarControl

    TNND,没辙啊,没用过那么高级的玩意儿,暂时也没找到中文的详细帮助,简直就是蚂蚁搬家似的摸索,一点儿点儿来吧. 先是NavBarControl的界面样子,貌似可以通过 PaintStyleKind ...

  7. feilong's blog | 目录

    每次把新博客的链接分享到技术群里,我常常会附带一句:蚂蚁搬家.事实上也确实如此,坚持1篇1篇的把自己做过.思考过.阅读过.使用过的技术和教育相关的知识.方法.随笔.索引记录下来,并持续去改进它们,希望 ...

  8. cp/tar/用c语言编写程序 实现cp命令的效果

    1.cp (拷贝) 已存在文件路径  要拷贝的文件路径 实现cp命令的代码如下: #include <stdio.h> //因为要在命令中得到两个路径,所以要用到main函数的两个参数 i ...

  9. 以应用带动SDN发展(CDN峰会 工信部杨崑)(转)

    以应用带动SDN发展(CDN峰会 工信部杨崑)   SDNAP推荐:这是在亚太全媒体SDN峰会由工信部研究院秘书长杨崑做的关于SDN的一个演讲,本人认为主讲者通过对整 个信息服务体系的精简归纳总结,剥 ...

随机推荐

  1. Java观察者模式(Observer模式)

    Java深入到一定程度,就不可避免的碰到设计模式(design pattern)这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模式在java的中型系统中应用广泛,遵循 ...

  2. Swift - enumerateObjectsUsingBlock的用法

    enumerateobjectsusingblock:不是Array的方法在NSArray使用.如果你想使用它,你需要一个实例NSArray而不是Array. import Foundation va ...

  3. MyEclipse生成WAR包并在Tomcat下部署发布(转发)

    从来没有想过web项目还能打包的,但是有要求,就不得不去实现,在网上找了一下,发现挺简单的. 首先是使用MyEclipse将web项目打包,如下图所示. 右键选中项目,选择export. 然后选择J2 ...

  4. grep -v 排除多人字符串

    # egrep -v '^$|^#' /etc/httpd/conf/httpd.conf # grep -v '^$\|^#' /etc/httpd/conf/httpd.conf

  5. HTML5 – 1.基础

    新网页结构 1.<header> 定义了文档的头部区域 2.<nav>标签定义导航链接的部分. 3.<article>定义页面独立的内容区域. 4.<sect ...

  6. Delphi之DLL知识学习1---什么是DLL

    DLL(动态链接库)是程序模块,它包括代码.数据或资源,能够被其他的Windows 应用程序共享.DLL的主要特点之一是应用程序可以在运行时调入代码执行,而不是在编译时链接代码,因此,多个应用程序可以 ...

  7. 使用Asyncio的Coroutine来实现一个有限状态机

    如图: #!/usr/bin/env python # -*- coding: utf-8 -*- import asyncio import datetime import time from ra ...

  8. Creating a Table View Programmatically

    https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TableView_iPhone/Cre ...

  9. [Maven] Missing artifact (解决办法)

    在使用Eclipse的Maven插件时,经常会遇到Missing artifact的编译错误,特别是在新环境中搭建相关项目时,经常出现类似此问题,今天一位同事又遇到了,经过一顿问题原因查找,始终无法解 ...

  10. BZOJ 1588: [HNOI2002]营业额统计 双向链表 / splay / treap

    1588: [HNOI2002]营业额统计 Description 营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况. Tiger ...