Codeforces 题目传送门 & 洛谷题目传送门

首先需发现一个性质,那就是每一个连通块所对应的是一个区间。换句话说 \(\forall l<r\),若 \(l,r\) 在同一连通块中,那 \(\forall x\in(l,r)\),\(x\) 也在 \(l,r\) 所在的连通块中。

简单证明一下罢:

  • 若 \(a_l<a_r\),那么 \(\forall x\in(l,r)\),若 \(a_x<a_r\),那么 \(x\) 与 \(r\) 连通;若 \(a_x\ge a_r\),则 \(a_x>a_l\),\(x\) 与 \(l\) 连通,符合题意。
  • 若 \(a_l\ge a_r\),由于 \(l,r\) 连通,必定存在 \(x<l\) 满足 \(a_x<a_l,a_x<a_r\);或者存在 \(x>r\) 满足 \(a_x>a_l,a_x>a_r\)。若是第一种情况,可将 \(x\) 看作新的 \(l\),这样可归约到 \(a_l<a_r\) 的情况;若是第二种情况,可将 \(x\) 看作新的 \(r\),这样也可归约到 \(a_l<a_r\) 的情况。

u1s1 我连这个性质都没看出来,可见我要脑子每脑子,要智商没智商/wq/wq

接下来考虑怎样判定 \(i,i+1\) 是否属于同一个连通块,根据上面的推论,\(i,i+1\) 不属于同一连通块当且仅当 \([1,i]\) 与 \([i+1,n]\) 之间没有边相连,即 \(\min\limits_{j=1}^ia_j>\max\limits_{j=i+1}^na_j\)。我们考虑枚举 \(\max\limits_{j=i+1}^na_j=w\),并将序列中 \(>w\) 的数设为 \(1\),\(\le w\) 的数设为 \(0\),那么 \(w\) 满足条件当且仅当得到的序列为 \(111\dots11000\dots00\) 的形式。又显然 \(w\) 必定在 \(a\) 序列中出现过,故我们的目标是统计有多少个数 \(x\) 在 \(a\) 序列中出现过,并且满足将 \(>x\) 的数设为 \(1\),\(\le x\) 的数设为 \(0\) 之后,得到的序列为 \(111\dots1000\dots00\) 的形式。这个东西怎么维护呢?我们设 \(f_w\) 为当 \(x=w\) 时序列中 \(10\) 段的个数,那我们只需统计 \(f_w=1\) 的 \(w\) 个数即可。我们以值为下标建一棵线段树,下标为 \(i\) 的位置为 \(f_i\) 的值。对于 \(i\in[0,n]\),我们令 \([\min(a_i,a_{i+1}),\max(a_i,a_{i+1}))\) 的 \(f_w\) 加 \(1\),表示当 \(w\in[\min(a_i,a_{i+1}),\max(a_i,a_{i+1}))\) 时 \(i,i+1\) 会产生一对 \(10\)。其中 \(a_0=\infty,a_{n+1}=0\),表示我们强制令第 \(0\) 位对应的 \(01\) 值为 \(1\),第 \(n+1\) 位对应的 \(01\) 值为 \(0\),然后这边又是个套路,由于对于 \(\forall w\) 必有 \(f_w>0\),故我们只需统计全局最小值个数,就是 \(f_w=1\) 的个数即可。

时间复杂度线性对数。

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=5e5;
const int MAXV=1e6;
int n,qu,a[MAXN+5];
struct node{int l,r,mn,mnc,lz;} s[MAXV*4+5];
void pushup(int k){
s[k].mn=min(s[k<<1].mn,s[k<<1|1].mn);s[k].mnc=0;
if(s[k].mn==s[k<<1].mn) s[k].mnc+=s[k<<1].mnc;
if(s[k].mn==s[k<<1|1].mn) s[k].mnc+=s[k<<1|1].mnc;
}
void build(int k,int l,int r){
s[k].l=l;s[k].r=r;if(l==r) return;
int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
}
void pushdown(int k){
if(s[k].lz){
s[k<<1].mn+=s[k].lz;s[k<<1].lz+=s[k].lz;
s[k<<1|1].mn+=s[k].lz;s[k<<1|1].lz+=s[k].lz;
s[k].lz=0;
}
}
void modify_mnc(int k,int p,int x){
if(s[k].l==s[k].r){s[k].mnc+=x;return;}
pushdown(k);int mid=s[k].l+s[k].r>>1;
if(p<=mid) modify_mnc(k<<1,p,x);
else modify_mnc(k<<1|1,p,x);
pushup(k);
}
void modify(int k,int l,int r,int x){
if(l>r) return;
if(l<=s[k].l&&s[k].r<=r){s[k].lz+=x;s[k].mn+=x;return;}
pushdown(k);int mid=s[k].l+s[k].r>>1;
if(r<=mid) modify(k<<1,l,r,x);
else if(l>mid) modify(k<<1|1,l,r,x);
else modify(k<<1,l,mid,x),modify(k<<1|1,mid+1,r,x);
pushup(k);
}
void update(int x,int v){modify(1,min(a[x],a[x+1]),max(a[x],a[x+1])-1,v);}
int main(){
scanf("%d%d",&n,&qu);multiset<int> st;a[0]=MAXV+1;a[n+1]=0;
for(int i=1;i<=n;i++) scanf("%d",&a[i]),st.insert(a[i]);build(1,0,MAXV);
for(int i=1;i<=n;i++) modify_mnc(1,a[i],1);
for(int i=0;i<=n;i++) update(i,1);
while(qu--){
int x,v;scanf("%d%d",&x,&v);st.erase(st.find(a[x]));
update(x-1,-1);update(x,-1);modify_mnc(1,a[x],-1);
a[x]=v;st.insert(v);
update(x-1,1);update(x,1);modify_mnc(1,a[x],1);
printf("%d\n",s[1].mnc);
}
return 0;
}

Codeforces 1270H - Number of Components(线段树)的更多相关文章

  1. codeforces Good bye 2016 E 线段树维护dp区间合并

    codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...

  2. codeforces 22E XOR on Segment 线段树

    题目链接: http://codeforces.com/problemset/problem/242/E E. XOR on Segment time limit per test 4 seconds ...

  3. Codeforces GYM 100114 D. Selection 线段树维护DP

    D. Selection Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Descriptio ...

  4. [Codeforces]817F. MEX Queries 离散化+线段树维护

    [Codeforces]817F. MEX Queries You are given a set of integer numbers, initially it is empty. You sho ...

  5. CodeForces 1099F - Cookies - [DFS+博弈+线段树]

    题目链接:https://codeforces.com/problemset/problem/1099/F Mitya and Vasya are playing an interesting gam ...

  6. Codeforces 834D The Bakery - 动态规划 - 线段树

    Some time ago Slastyona the Sweetmaid decided to open her own bakery! She bought required ingredient ...

  7. ACM Minimum Inversion Number 解题报告 -线段树

    C - Minimum Inversion Number Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d &a ...

  8. Codeforces 588E. A Simple Task (线段树+计数排序思想)

    题目链接:http://codeforces.com/contest/558/problem/E 题意:有一串字符串,有两个操作:1操作是将l到r的字符串升序排序,0操作是降序排序. 题解:建立26棵 ...

  9. Codeforces Gym 100803G Flipping Parentheses 线段树+二分

    Flipping Parentheses 题目连接: http://codeforces.com/gym/100803/attachments Description A string consist ...

随机推荐

  1. for...in和Object.keys()区别

    区别: for in 用来枚举对象的属性,某些情况下,可能按照随机顺序遍历数组元素 object.keys() 可以返回对象属性为元素的数组,数组中属性名顺序和for in比那里返回顺序一样 ---f ...

  2. 关于ORBSLAM的发展脉络

    ORBSLAM系列存在随机性的原因:RANSAC中随机数生成器的使用:跟踪.映射和回环闭合线程的不可预测的交织,这取决于操作系统调度程序,这种不可预测性使得在不同的执行中估计的关键帧的姿势可能不同,甚 ...

  3. 主仆见证了 Hobo 的离别 题解

    前言: 题面挺神仙.反正我考试的时候看了40分钟也没看懂. 后来改题感觉自己写的挺假,没想到加个\(k==1\)的特判竟然就A了?无语力. 解析: 看懂题以后就好说了.首先这显然是一个树形结构.我们考 ...

  4. 2021.10.18考试总结[NOIP模拟76]

    T1 洛希极限 不难发现每个点肯定是被它上一行或上一列的点转移.可以预处理出每个点上一行,上一列最远的能转移到它的点,然后单调队列优化. 预处理稍显ex.可以用并查集维护一个链表,记录当前点之后第一个 ...

  5. 2021.6.17考试总结[NOIP模拟8]

    T1 星际旅行 其实就是求两条只走一遍的边的方案数. 考场上第一眼就感觉不可做,后来画了几个图,发现好像只要两个边是相连的就可以只走一遍,居然还真拿了30.. 其实是一道欧拉路的题,把每条非自环的边看 ...

  6. Python课程笔记(九)

    本次课程主要学习了Excel和JSON格式的一些读写操作.课程代码 一.Excel数据读写操作 1.安装模块 pip install xlrd pip install xlwt 网不好可以采用三方库: ...

  7. 算法:Z字型(Zigzag)编排

    问题:给定 n 行和 m 列的二维数组矩阵.如图所示,以 ZIG-ZAG 方式打印此矩阵. 从对称的角度来看,通过反复施加滑行反射可以从简单的图案如线段产生规则的之字形. 主要思想:算法从(0, 0) ...

  8. 创建线程 出现SIGSEGV crash

    在Opwrt平台上测试ok的一个网络传输延时测试demo程序移植到Android平台后,运行出现莫名其妙的SIGSEGV crash. 仔细检查过源码,特别是指针等后未发现问题. --------- ...

  9. PCIe知识摘要记录

    摘: 一. 在PCIe的Spec中,并没有特别详细的关于Root Complex的定义,从实际的角度来讲,可以把Root Complex理解为CPU与PCIe总线系统通信的媒介.Endpoint处于P ...

  10. (二)FastDFS 高可用集群架构学习---搭建

    一.单group 单磁盘 的 FastDFS 集群 a.前期准备 1.系统软件说明: 名称 说明 CentOS 7.x(安装系统) libfastcommon FastDFS分离出的一些公用函数包 F ...