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. UltraSoft - Alpha - Scrum Meeting 1

    Date: Apr 06th, 2020. 会议内容为讨论功能规格书和技术规格书的撰写. Scrum 情况汇报 进度情况 组员 负责 昨日进度 后两日任务 CookieLau PM.后端 进行Djan ...

  2. Mac上安装Grafana

    Mac上安装Grafana 一.背景 二.安装步骤 1.通过 Home Brew 安装 2.通过二进制包进行安装 1.下载 2.grafana配置文件的路径 3.修改grafana配置 1.修改默认的 ...

  3. freemarker自定义指令

    最近项目中使用了spring boot搭建项目,使用spring security管理项目中的权限,使用freemarker作为视图层.为了将权限控制到按钮上,因此考虑直接使用spring secur ...

  4. gdal3.1.0+VS2017+geos+kml编译总结

    1.简介 gdal3.1.0编译过程中必须依赖proj,编译gdal必须要编译proj,proj的编译需要sqlite3,因此想要编译gdal3.1.0需要先编译proj和sqlite3 2.关于sq ...

  5. Python中的括号()、[]、{}

    长时间不用容易混淆,仅记! 在Python语言中最常见的括号有三种,分别是:小括号().中括号[].花括号{} . Python中的小括号(): 代表tuple元祖数据类型,元祖是一种不可变序列.大多 ...

  6. DDD领域驱动设计-项目包结构说明-Ⅳ

     基于DDD领域驱动设计的思想,在开发具体系统时,需要先建立不同的层级包.主要是梳理不同层面(应用层,领域层,基础设施层,展示层)包括的功能目录,每一个层面应该包括哪些模块.本例所讲述的分层是DDD落 ...

  7. Linux调整时区和同步时间

    1.调整时区 tzselect 选择Asia -> China -> Beijing Time 2.设置为默认时区 cp -f /usr/share/zoneinfo/Asia/Shang ...

  8. Centos 7 编译安装llvm 8.0.0

    参考连接:https://www.cnblogs.com/BinBinStory/p/7499527.html https://blog.csdn.net/llwy1428/article/detai ...

  9. Ubuntu安装数据库

    1.通过命令行安装:sudo apt-get install mysql-client mysql-server 2.安装过程中输入数据库密码("123456",root) 3.使 ...

  10. 使用gitlab runner 进行CI(四):使用Gitlab Page托管项目文档

    目录 1.什么是Gitlab Pages 2.开启Gitlab Pages 3.基本过程 4.托管markdown文档 4.1 安装sphinx等依赖 4.2 配置项目的sphinx配置 4.3 编写 ...