BZOJ2888 : 资源运输

显然资源集合处就是树的重心,这题需要动态维护树的重心。

每个连通块以重心为根,用link-cut tree维护每个点的子树大小以及子树内所有点到它的距离和。

合并两个连通块时,考虑启发式合并,暴力往大的树中添加叶子。

添加叶子时,需要将叶子到重心路径上所有点的子树大小+1,距离和则加上一个等差数列。

并且新的重心是可能是原来的重心或者原来重心到叶子路径上的第一个点,暴力即可。

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

 

#include<cstdio>
#define N 40010
int n,m,i,x,y,ans;char op[5];
int g[N],v[N<<1],nxt[N<<1],ed,f[N],son[N][2],val[N],tag[N],sum[N],ts[N],td[N],size[N],tmp[N];
inline void swap(int&a,int&b){int c=a;a=b;b=c;}
inline bool isroot(int x){return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;}
inline void add1(int x,int p){if(!x)return;val[x]+=p;tag[x]+=p;}
inline void add2(int x,int s,int d){if(!x)return;sum[x]+=s+size[son[x][1]]*d;ts[x]+=s;td[x]+=d;}
inline void pb(int x){
  if(tag[x]){
    add1(son[x][0],tag[x]);
    add1(son[x][1],tag[x]);
    tag[x]=0;
  }
  if(td[x]){
    add2(son[x][0],ts[x]+(size[son[x][1]]+1)*td[x],td[x]);
    add2(son[x][1],ts[x],td[x]);
    ts[x]=td[x]=0;
  }
}
inline void up(int x){size[x]=size[son[x][0]]+size[son[x][1]]+1;}
inline void rotate(int x){
  int y=f[x],w=son[y][1]==x;
  son[y][w]=son[x][w^1];
  if(son[x][w^1])f[son[x][w^1]]=y;
  if(f[y]){
    int z=f[y];
    if(son[z][0]==y)son[z][0]=x;else if(son[z][1]==y)son[z][1]=x;
  }
  f[x]=f[y];f[y]=x;son[x][w^1]=y;up(y);
}
inline void splay(int x){
  int s=1,i=x,y;tmp[1]=i;
  while(!isroot(i))tmp[++s]=i=f[i];
  while(s)pb(tmp[s--]);
  while(!isroot(x)){
    y=f[x];
    if(!isroot(y)){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}
    rotate(x);
  }
  up(x);
}
inline void access(int x){for(int y=0;x;y=x,x=f[x])splay(x),son[x][1]=y,up(x);}
inline int root(int x){access(x);splay(x);while(son[x][0])x=son[x][0];return x;}
inline void addleaf(int x,int y){
  f[y]=x,son[y][0]=son[y][1]=val[y]=tag[y]=sum[y]=ts[y]=td[y]=0,size[y]=1;
  x=root(x),access(y),splay(x),add1(x,1),add2(x,0,1);
  for(y=son[x][1];son[y][0];y=son[y][0]);splay(y);
  int vx=val[x],vy=val[y];
  if(vy*2>vx){
    val[y]=vx,val[x]-=vy;
    sum[x]-=sum[y]+vy,sum[y]+=sum[x]+vx-vy;
    access(y),splay(x),son[x][0]=y,son[x][1]=0;
  }
}
void dfs(int x,int y){
  addleaf(y,x);
  for(int i=g[x];i;i=nxt[i])if(v[i]!=y)dfs(v[i],x);
}
inline void addedge(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
inline void link(int x,int y){
  int X=root(x),Y=root(y);
  ans-=sum[X]+sum[Y];
  if(val[X]<val[Y])swap(x,y);
  dfs(y,x),addedge(x,y),addedge(y,x);
  ans+=sum[root(x)];
}
int main(){
  scanf("%d%d",&n,&m);
  for(i=1;i<=n;i++)val[i]=size[i]=1;
  while(m--){
    scanf("%s",op);
    if(op[0]==‘A‘)scanf("%d%d",&x,&y),link(x,y);
    if(op[0]==‘Q‘)printf("%d\n",ans);
  }
  return 0;
}

  

时间: 2024-10-21 20:53:57

BZOJ2888 : 资源运输的相关文章

【BZOJ-2888】资源运输 LCT + 启发式合并

2888: 资源运输 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 63  Solved: 33[Submit][Status][Discuss] Description 小Y盯上了最近发行的即时战略游戏——ResourceTransport.但在前往通关之路的道路上,一个小游戏挡住了小Y的步伐.“国家的本质是生产与收集资源”是整款游戏的核心理念,这个小游戏也不例外.简单的说,用户需要管理一个国家,使其繁荣富强. 一个国家含有N个城市,游戏开始时

BZOJ 2888: 资源运输

Description 加边,询问连通块中所有点到重心的距离. Solution LCT. http://www.cnblogs.com/clrs97/p/4776809.html 一开始没想到怎么合并两颗树时候计算贡献... Code /************************************************************** Problem: 2888 User: BeiYu Language: C++ Result: Accepted Time:1560

BZOJ 2888 资源运输(启发式合并LCT)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2888 [题目大意] 不断加边,问每个连通块的重心到其它点的距离和的和 [题解] 启发式合并LCT,通过维护等差数列的首项和公差 来实现保存子树内所有节点到这个节点的距离之和. [代码] #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const in

YCB 的暑期计划

前言 YCB现在很弱(TAT) 暑假有一个月,赶快狂补一下. 大概的计划如下: 首先前期会以数据结构为主,毕竟代码能力太弱,涉及内容:线段树分治.二进制分组.KD-Tree. 等数据结构做到没有智商的时候加入一波数论,内容为 杜教筛.min_25筛. 然后中途小清新一下,做一些 组合博弈与构造题. 接着继续练代码能力,顺便学一些神奇的暴力:启发式合并.dsu on tree . 然后图论也忘的差不多了,就回过头去学点新东西,大概会有spfa判负环.0/1分数规划.差分约束. 估计这个时候也没有什

一些$LCT$的瓜皮题目

一些瓜皮 放几个比较优(she)秀(pi)的\(LCT\)题. 老惯例,每一题代码因为一些未知原因消失了(如果要的话私我好了,虽然会咕咕咕). 嘴巴\(AC\)真香! [SP16580] QTREE7 对黑色.白色各开一棵有根\(LCT\). 若\(x\)点加入颜色\(c\)集合,则在\(c\)的那颗\(LCT\)上连接\((x,fa_x)\),在另一棵上断掉父亲边. 查询时,首先判断根结点是否在当前颜色集合内. 如果在的话直接查整棵\(LCT\). 否则走向右儿子,查询对应子树. 什么子树最大

【海岛帝国系列赛】No.3 海岛帝国:运输资源

海岛帝国:运输资源 [试题描述] YSF考虑到“药师傅”帝国现在资源极度不平均,于是,商讨启用南水北调工程.YZM为首席工程师.现在,YSF由于工作紧张,准备军用物资和民用物资.但他要时时关注运输工程动态,因为货物很珍贵,是最新发明的T-2500智能生产行业制造机.用于工.农业生产,而且技术先进,数量众多,不能落入恐怖分子之手.YSF要YZM向他随时汇报货物走向.货物地点,以防万一恐怖分子袭击.脾气暴躁的YZM一向不爱干这种统筹规划的杂活.所以,YZM需要你来帮他编一个小程序,来随时给多疑的YS

首师大附中科创教育平台 我的刷题记录 0324 99999999海岛帝国:运输资源

今天给大家献上“C”级题:99999999海岛帝国:运输资源!! 试题编号:0324   99999999海岛帝国:运输资源 难度级别:C: 运行时间限制:1000ms: 运行空间限制:256000KB: 代码长度限制:2000000B 试题描述      YSF考虑到“药师傅”帝国现在资源极度不平均,于是,商讨启用南水北调工程.YZM为首席工程师.现在,YSF由于工作紧张,准备军用物资和民用物资.但他要时时关注运输工程动态,因为货物很珍贵,是最新发明的T-2500智能生产行业制造机.用于工.农

[HNOI2014]米特运输

题目描述 米特是D星球上一种非常神秘的物质,蕴含着巨大的能量.在以米特为主要能源的D星上,这种米特能源的运输和储存一直是一个大问题. D星上有N个城市,我们将其顺序编号为1到N,1号城市为首都.这N个城市由N-1条单向高速通道连接起来,构成一棵以1号城市(首部)为根的树,高速通道的方向由树中的儿子指向父亲.树按深度分层:根结点深度为0,属于第1层:根结点的子节点深度为1,属于第2层:依此类推,深度为i的结点属于第i+l层. 建好高速通道之后,D星人开始考虑如何具体地储存和传输米特资源.由于发展程

[BZOJ 3573][Hnoi2014]米特运输(乱搞)

Description 米特是D星球上一种非常神秘的物质,蕴含着巨大的能量.在以米特为主要能源的D星上,这种米特能源的运输和储 存一直是一个大问题.D星上有N个城市,我们将其顺序编号为1到N,1号城市为首都.这N个城市由N-1条单向高速 通道连接起来,构成一棵以1号城市(首部)为根的树,高速通道的方向由树中的儿子指向父亲.树按深度分层: 根结点深度为0,属于第1层:根结点的子节点深度为1,属于第2层:依此类推,深度为i的结点属于第i+l层.建好 高速通道之后,D星人开始考虑如何具体地储存和传输米