OTOCI

题目大意

给定 \(n\) 个带权的点,需要进行四种操作:查询两点连通性;加边;修改点权;查询两点路径的权值和。

思路分析

首先观察题目,我们会发现,在所有的操作结束后,所有的点构成一个森林,这是因为题目中的加边是建立在两点不连通的基础上的,所以不会形成任何的环,到最后自然形成了一个森林。

那么,我们可以不用理会题目的“要求在线处理所有操作”,使用离线大法跑树链剖分来解决了。

具体的说,我们先将所有的询问存下来离线处理,先用并查集维护两点的连通性和加边操作,然后在最后形成的森林上跑树剖,再依次处理每个询问。

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

代码

#include <bits/stdc++.h>
using namespace std;
const int N=100100;//双向边 int to[N],nxt[N],head[N],w[N];
int fat[N],son[N],dep[N],siz[N],top[N],dfn[N],rnk[N];//树剖七件套
int idx,n,m,in1,in2,q,cnt;
int fa[N],inp[N*3][3];char op[15];//并查集,询问 int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}//常规并查集
void add(int u,int v){idx++;to[idx]=v;nxt[idx]=head[u];head[u]=idx;}
void Swap(int &x,int &y){int t=x;x=y;y=t;} struct STn{int l,r,sum;};//线段树求区间和
struct ST{
STn a[N<<2];
void build(int p,int l,int r){
a[p].l=l;a[p].r=r;
if(a[p].l==a[p].r){a[p].sum=w[rnk[a[p].l]];return ;}
int mid=(a[p].l+a[p].r)>>1;
build(p<<1,l,mid);build(p<<1|1,mid+1,r);
a[p].sum=a[p<<1].sum+a[p<<1|1].sum;return ;
}
void change(int p,int x,int k){//单点修改
if(a[p].l==a[p].r){a[p].sum=k;return ;}
int mid=(a[p].l+a[p].r)>>1;
if(x<=mid) change(p<<1,x,k);else change(p<<1|1,x,k);
a[p].sum=a[p<<1].sum+a[p<<1|1].sum;return ;
}
int ask(int p,int l,int r){//求和
if(l<=a[p].l&&a[p].r<=r) return a[p].sum;
int mid=(a[p].l+a[p].r)>>1;
return ((l<=mid)?ask(p<<1,l,r):0)+((r>mid)?ask(p<<1|1,l,r):0);
}
}tree; void dfs_1(int s,int gr){//常规树剖dfs
dep[s]=dep[gr]+1;fat[s]=gr;
son[s]=-1;siz[s]=1;
for(int i=head[s];i;i=nxt[i]){
int v=to[i];
if(v==gr) continue;
dfs_1(v,s);
siz[s]+=siz[v];
if(son[s]==-1||siz[v]>siz[son[s]]) son[s]=v;
}
} void dfs_2(int s,int tp){
top[s]=tp;dfn[s]=++cnt;rnk[cnt]=s;
if(son[s]==-1) return ;
dfs_2(son[s],tp);
for(int i=head[s];i;i=nxt[i]){
int v=to[i];
if(v!=son[s]&&v!=fat[s]) dfs_2(v,v);
}
} int query(int x,int y){//树剖求链和
int res=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) Swap(x,y);
res+=tree.ask(1,dfn[top[x]],dfn[x]);
x=fat[top[x]];
}
res+=tree.ask(1,min(dfn[x],dfn[y]),max(dfn[x],dfn[y]));
return res;
} int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
scanf("%d",&q);
for(int i=1;i<=q;i++){
scanf("%s%d%d",op+1,&in1,&in2);
if(op[1]=='b'){
if(find(in1)==find(in2)) inp[i][0]=9;
else{inp[i][0]=10;fa[find(in1)]=find(in2);add(in1,in2);add(in2,in1);}//加边
}
if(op[1]=='p'){inp[i][0]=1;inp[i][1]=in1;inp[i][2]=in2;}
if(op[1]=='e'){
if(find(in1)!=find(in2)) inp[i][0]=11;
else{inp[i][0]=2;inp[i][1]=in1;inp[i][2]=in2;}
}
}
for(int i=1;i<=n;i++)
if(!fat[i]){dfs_1(i,0);dfs_2(i,i);}//跑多次树剖
tree.build(1,1,n);
for(int i=1;i<=q;i++){//离线操作
if(inp[i][0]==9){puts("no");continue;}
if(inp[i][0]==10){puts("yes");continue;}
if(inp[i][0]==11){puts("impossible");continue;}
if(inp[i][0]==1){tree.change(1,dfn[inp[i][1]],inp[i][2]);}
if(inp[i][0]==2){cout<<query(inp[i][1],inp[i][2])<<'\n';}//回答询问
}
return 0;
}

OTOCI 题解的更多相关文章

  1. 【题解】 Luogu P4312 / SP4155 [COCI 2009] OTOCI / 极地旅行社

    原题地址:P4312 [COCI 2009] OTOCI / 极地旅行社/SP4155 OTOCI - OTOCI lct入门难度的题,十分弱智(小蒟蒻说lct是什么,能吃吗?) bridge操作判联 ...

  2. SPOJ - OTOCI LCT

    OTOCI Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/problem/viewProblem. ...

  3. [luogu]P4312 [COCI 2009] OTOCI / 极地旅行社(LCT)

    P4312 [COCI 2009] OTOCI / 极地旅行社 题目描述 不久之前,Mirko建立了一个旅行社,名叫"极地之梦".这家旅行社在北极附近购买了N座冰岛,并且提供观光服 ...

  4. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  5. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  6. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  7. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  8. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  9. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  10. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

随机推荐

  1. SQL 查询 总结 【行子查询 ; 列子查询 ; 表子查询 ; 自链接 ; 内连接 ;外连接 ; 无规则链接 ……】

    简单介绍一下连接方式: 1.1.使用无连接规则连接两表  无限规则  也就简单的 select * from tableA , tableB  即得到一个笛卡尔积.  什么是 笛卡尔积 在 我的 另外 ...

  2. Vue 先初始化子组件再初始化父组件的方法(自定义父子组件mounted执行顺序)

    写在前面: 本篇内容内容主要讲述了,在使用 Konva 进行开发过程中遇到的一些问题.(既然是组件加载顺序,主要牵扯到的就是,父子组件的关系,父子组件的生命周期) 众所周知,Vue中父子组件生命周期的 ...

  3. Flutter ncnn 使用

    Flutter 实现手机端 App,如果想利用 AI 模型添加新颖的功能,那么 ncnn 就是一种可考虑的手机端推理模型的框架. 本文即是 Flutter 上使用 ncnn 做模型推理的实践分享.有如 ...

  4. [NOIP2011 提高组] 聪明的质监员【题解】

    题目 小 T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有 \(n\) 个矿石,从 \(1\) 到 \(n\) 逐一编号,每个矿石都有自己的重量 \(w_i\) 以及价值 \(v_i\) ...

  5. 文心一言 VS 讯飞星火 VS chatgpt (66)-- 算法导论6.5 5题

    五.试分析在使用下列循环不变量时,HEAP-INCREASE-KEY 的正确性:在算法的第4~6行 while循环每次迭代开始的时候,子数组 A[1..A.heap-size]要满足最大堆的性质.如果 ...

  6. 痞子衡嵌入式:恩智浦i.MX RT1xxx系列MCU启动那些事(10.A)- FlexSPI NAND启动时间(RT1170)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RT1170 FlexSPI NAND启动时间. 本篇是 i.MXRT1170 启动时间评测第四弹,前三篇分别给大家评测 ...

  7. 记一次使用pagehelper的坑(返回的total和size每页条数一致的问题)

    问题描述 众所周知,pagehelper使用时应该在dao查询语句的前一句加上PageHelper.startPage,所以标题的问题由此引出-- 原因 PageHelper.startPage使用后 ...

  8. 快速解决 const 与 typedef 类型组合时 ,const修饰谁的问题

    C++使用typedef 给复合类型定义别名时,与const结合会产生看似"令人困惑"的类型推定,例如 typedef char* pstring; const pstring c ...

  9. uniapp封装接口

    1 为什么需要封装接口 封装接口是为了提高开发效率.增加代码复用性和提升可维护性.下面对这些原因进行详细解释: 1.1 开发效率 开发效率:减少代码量,简化调用过程 通过封装接口,可以将一些常见的操作 ...

  10. MySql Workbench 迁移工具 migration 提示缺少pyodbc 2.1.8 的解决方法

    想把公司的数据库转到MySQL,所以想装个MySQL测试,发现新版的MySQL(8.0.34)默认安装还是有不少问题, 一.譬如表.字段大小写的问题: lower_case_table_names=0 ...