BZOJ1841 : 蚂蚁搬家
树分治,对于每个分治结构,维护两棵线段树。
第一棵按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 : 蚂蚁搬家的更多相关文章
- 计蒜客模拟赛5 D2T2 蚂蚁搬家
很久很久以前,有很多蚂蚁部落共同生活在一片祥和的村庄里.但在某一天,村庄里突然出现了一只食蚁兽,蚂蚁们为了保全性命而决定搬家. 然而这个村庄四面环山,想要离开这个村庄必须要从地洞里离开,村子里一共有 ...
- 蚂蚁的难题(二)首尾相连数组的最大子数组和(DP)
蚂蚁的难题(二) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 下雨了,下雨了,蚂蚁搬家了. 已知有n种食材需要搬走,这些食材从1到n依次排成了一个圈.小蚂蚁对每种食材 ...
- NYOJ 745 蚂蚁问题(两)
蚂蚁的难题(二) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描写叙述 下雨了,下雨了.蚂蚁搬家了. 已知有n种食材须要搬走,这些食材从1到n依次排成了一个圈.小蚂蚁对每种 ...
- NYOJ 745 蚂蚁的难题(二)
蚂蚁的难题(二) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 下雨了,下雨了,蚂蚁搬家了. 已知有n种食材需要搬走,这些食材从1到n依次排成了一个圈.小蚂蚁对每种 ...
- Burndown chart
S型的燃尽图 在一次milestone开发过程中,开发者会持续编辑issue列表,每个issue都有自己的生命周期.燃尽图预期这些issues会被线性的消灭掉,所以从第一天直接到最后一天画个直线表示预 ...
- DevExpress 学习使用之 NavBarControl
TNND,没辙啊,没用过那么高级的玩意儿,暂时也没找到中文的详细帮助,简直就是蚂蚁搬家似的摸索,一点儿点儿来吧. 先是NavBarControl的界面样子,貌似可以通过 PaintStyleKind ...
- feilong's blog | 目录
每次把新博客的链接分享到技术群里,我常常会附带一句:蚂蚁搬家.事实上也确实如此,坚持1篇1篇的把自己做过.思考过.阅读过.使用过的技术和教育相关的知识.方法.随笔.索引记录下来,并持续去改进它们,希望 ...
- cp/tar/用c语言编写程序 实现cp命令的效果
1.cp (拷贝) 已存在文件路径 要拷贝的文件路径 实现cp命令的代码如下: #include <stdio.h> //因为要在命令中得到两个路径,所以要用到main函数的两个参数 i ...
- 以应用带动SDN发展(CDN峰会 工信部杨崑)(转)
以应用带动SDN发展(CDN峰会 工信部杨崑) SDNAP推荐:这是在亚太全媒体SDN峰会由工信部研究院秘书长杨崑做的关于SDN的一个演讲,本人认为主讲者通过对整 个信息服务体系的精简归纳总结,剥 ...
随机推荐
- EventBus学习入门
EventBus Features What makes greenrobot's EventBus unique, are its features: Simple yet powerful: Ev ...
- 利用bak文件恢复数据库问题小结
对备份的基础理解: --完整备份:完整备份会备份所有数据的区和少量的日志(日志文件用于恢复数据保持数据一致性).由于差异备份需要依据最后一次完整备份,因此完整备份会清楚一些分配位图数据. --差异备份 ...
- 谈谈Delphi中的类和对象1---介绍几个概念 && 对象是一个地地道道的指针
参考:http://blog.163.com/liang_liu99/blog/static/88415216200952123412180/ 以下的介绍主要针对的是Delphi的面向对象的知识,可能 ...
- 【131031】rel 属性 -- link标签中的rel属性,定义了文档与链接的关系
此属性通常出现在a,link标签中 属性值 Alternate -- 定义交替出现的链接 Alternate 属性值 -- alternate是LinkTypes的一个值,网页设计者可以通过此值,设计 ...
- babyClock 1.0发布(Android2.2以上)
[总体说明] babyClock是以天为单位,进行提醒的小工具:可以设置多个闹钟,每个闹钟又按照频率分为多个提醒:过期后自动设置到明天该时刻进行提醒. 一个闹钟包含时间区段.提醒频率:进入时间区段时, ...
- 攻城狮在路上(叁)Linux(二十七)--- 压缩与打包之常见的压缩命令
前面讲到,linux中的后缀名没有特殊的意义,一般是作为不同文件类型的标识而已.下面是与打包.压缩相关的后缀名介绍: *.z:compress程序压缩文件 *.gz:gzip程序压缩文件 *.bz2: ...
- 攻城狮在路上(叁)Linux(二十二)--- linux磁盘挂载与卸载 mount umount
挂载就是将文件系统与目录结合的操作.挂载点就是目录,该目录就是进入分区或文件系统的入口. 一.挂载前的注意事项: 1.单一文件系统不应该被重复挂载在不同的挂载点中. 2.单一目录不应该重复挂载多个文件 ...
- 修改tomcat默认编码
实际项目中一般是用utf-8的,而Tomcat的默认编码则是iso-8859-1, 因此我们通常编辑conf/下的server.xml,配置Connector项,加上属性URIEncoding=&qu ...
- Win10 UAP 绑定
Compiled DataBinding in Windows Universal Applications (UAP) http://nicksnettravels.builttoroam.com/ ...
- hdu 4039 2011成都赛区网络赛I ***
两层搜索,直接for循环就行了,还要注意不能是自己的朋友 #include<cstdio> #include<iostream> #include<algorithm&g ...