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. 写了10000条Airtest截图脚本总结出来的截图经验,赶紧收藏!

    前言 今天想先给大家分享1个小白用户的Airtest从入门到放弃的故事: 小A是一个自动化的小白,在逛测试论坛的时候,偶然间发现了Airtest这个基于图像识别的UI自动化框架. 出于好奇,小A试用了 ...

  2. Java基础-Java8新特性

    一.Lambda表达式 在了解 Lambda 之前,首先回顾以下Java的方法. Java的方法分为实例方法,例如:Integer的equals()方法: public final class Int ...

  3. BUAA2020软工作业(一)——谈谈我和计算机的缘分

    项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 第一次作业-热身! 我在这个课程的目标是 进一步提高自己的编码能力,工程能力 这个作业在哪个具体方 ...

  4. 2021.10.7考试总结[NOIP模拟71]

    信心赛,但炸了.T3SB错直接炸飞,T4可以硬算的组合数非要分段打表求阶乘..T2也因为一个细节浪费了大量时间.. 会做难题很好,但首先还是要先把能拿的分都拿到. T1 签到题 结论:总可以做到对每个 ...

  5. bash执行顺序:alias --> function --> builtin --> program

    linux bash的执行顺序如下所示: 先 alias --> function --> builtin --> program 后 验证过程: 1,在bash shell中有内置 ...

  6. 重建二叉树 牛客网 剑指Offer

    重建二叉树 牛客网 剑指Offer 题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3, ...

  7. hdu 1227 Fast Food(DP)

    题意: X轴上有N个餐馆.位置分别是D[1]...D[N]. 有K个食物储存点.每一个食物储存点必须和某个餐厅是同一个位置. 计算SUM(Di-(离第i个餐厅最近的储存点位置))的最小值. 1 < ...

  8. hadoop前期准备

    最近想要学习一下hadoop,现在想边学习边记录下,方便以后自己或别人查看.(注意最好ubantu,jdk及其他软件选择32bit的,jdk最好7以上) 首先配置下jdk,下载下jdk的包,把jdk- ...

  9. Linux系统编程之进程概念

    注:本文部分图片来源于网络,如有侵权,请告知删除 1. 什么是进程? 在了解进程概念之前,我们需要先知道程序的概念. 程序,是指编译好的二进制文件,这些文件在磁盘上,并不占用系统资源. 进程,指的是一 ...

  10. LoadRunner12浏览器录制(谷歌火狐)

    一.使用谷歌浏览器 下载的版本 65.0.3325.162(正式版本)(64 位)安装之前要记得把电脑现有的谷歌浏览器卸载了. 1.下载地址:https://www.chromedownloads.n ...