CF 1405E Fixed Point Removal【线段树上二分】 

题意:

给定长度为\(n\)的序列\(A\),每次操作可以把\(A_i = i\)(即值等于其下标)的数删掉,然后剩下的数组拼接起来,问最多能删多少个数

\(q\)次独立询问,每次把前\(x\)个数和\(后\)后\(y\)个数置为\(n+1\)之后解决上述问题

题解:

先不考虑把前\(x\)个数和后\(y\)个数置成\(n+1\)的情况

首先我们可以想到的是把所有数的值减去其下标,定义\(B_i = A_i - i\),那么对于\(B_i=0\)的位置,一开始就是可以删除的,当删掉了第\(i\)个数之后,之前的数的下标没有变化,之后的数下标都减了\(1\),即对于所有\(j>i\)的\(B_j\)变成了\(B_j+1\),也就可能存在新的\(B_j=0\)的情况

根据上面的事实,那么一开始\(B_i>0\)的这些值永远也删不掉,且为了删除最多的数,每次肯定选择最右边的\(B_i=0\)的值进行删除(如果存在下标\(i,j\)且\(i<j,B_i=B_j=0\),如果先删除\(i\),那么\(j\)就删不掉了)

现在有一个推论:对于某个位置\(i\),如果\(B_i<=0\),那么在它之前至少存在\(-B_i\)个数被删掉,这个数就也可以被删除

那么对于每个位置\(i\),满足\(B_i\le0\),存在一个左边界\(l\),只要第\(l\)个元素能够删除,那么第\(i\)个元素也能被删除

左边界\(l\)需要满足只考虑\([l,i)\)区间的元素的情况下,可删除元素大于等于\(-B_i\)个,如果\(B_i=0\)显然\(l=i\)

那么对于每个存在左边界的\(i\)需要做的就是在\(l\)的位置加上\(1\),每个位置的值就表示以这个点为左边界的情况下能删除多少个数,找\(l\)的方法可以二分之后算区间和或者直接在线段树上二分,前者复杂度\(O(\log^2n)\)后者复杂度\(O(\log n)\)

考虑先把询问按右边界从小到大排序(即\(y\)从大到小排序),遍历每个询问,更新到\(i=n-y\)的位置,然后计算\([x+1,n-y]\)的区间和就好了

排序是因为要防止当前不合法的点对左边界产生贡献

view code
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast,no-stack-protector")
#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define endl "\n"
#define LL long long int
#define vi vector<int>
#define vl vector<LL>
#define all(V) V.begin(),V.end()
#define sci(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define scs(s) scanf("%s",s)
#define pii pair<int,int>
#define pll pair<LL,LL>
#ifndef ONLINE_JUDGE
#define cout cerr
#endif
#define cmax(a,b) ((a) = (a) > (b) ? (a) : (b))
#define cmin(a,b) ((a) = (a) < (b) ? (a) : (b))
#define debug(x) cerr << #x << " = " << x << endl
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
template <typename T> vector<T>& operator << (vector<T> &__container, T x){ __container.push_back(x); return __container; }
template <typename T> ostream& operator << (ostream &out, vector<T> &__container){ for(T _ : __container) out << _ << ' '; return out; }
const int MAXN = 3e5+7;
int n, q, A[MAXN];
pair<pii,int> Q[MAXN];
struct SegmentTree{
int sum[MAXN<<2], l[MAXN<<2], r[MAXN<<2];
#define ls(rt) rt << 1
#define rs(rt) rt << 1 | 1
void build(int L, int R, int rt = 1){
l[rt] = L; r[rt] = R;
sum[rt] = 0;
if(l[rt] + 1 == r[rt]) return;
int mid = (L + R) >> 1;
build(L,mid,ls(rt)); build(mid,R,rs(rt));
}
void modify(int pos, int x, int rt = 1){
sum[rt] += x;
if(l[rt] + 1 == r[rt]) return;
int mid = (l[rt] + r[rt]) >> 1;
if(pos<mid) modify(pos,x,ls(rt));
else modify(pos,x,rs(rt));
}
int qsum(int L, int R, int rt = 1){
if(L>=r[rt] or l[rt]>=R) return 0;
if(L<=l[rt] and r[rt]<=R) return sum[rt];
return qsum(L,R,ls(rt)) + qsum(L,R,rs(rt));
}
int qpos(int x, int rt = 1){
if(l[rt] + 1 == r[rt]) return l[rt];
if(sum[rs(rt)]>=x) return qpos(x,rs(rt));
else return qpos(x-sum[rs(rt)],ls(rt));
}
}ST;
int ret[MAXN];
void solve(){
sci(n); sci(q);
for(int i = 1; i <= n; i++) sci(A[i]), A[i] -= i;
for(int i = 1; i <= q; i++){
sci(Q[i].first.first); sci(Q[i].first.second);
Q[i].second = i;
}
sort(Q+1,Q+1+q,[&](pair<pii,int> &a, pair<pii,int> &b){ return a.first.second > b.first.second; });
int cur = 1, tot = 0;
ST.build(0,n+1);
for(int i = 1; i <= q; i++){
while(cur<=n-Q[i].first.second){
if(A[cur]==0) ST.modify(cur,1), tot++;
else if(A[cur]<0 and -A[cur]<=tot) ST.modify(ST.qpos(-A[cur]),1), tot++;
cur++;
}
ret[Q[i].second] = ST.qsum(Q[i].first.first+1,cur);
}
for(int i = 1; i <= q; i++) cout << ret[i] << endl;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("Local.in","r",stdin);
freopen("ans.out","w",stdout);
#endif
solve();
return 0;
}

CF 1405E Fixed Point Removal【线段树上二分】的更多相关文章

  1. LOJ 3059 「HNOI2019」序列——贪心与前后缀的思路+线段树上二分

    题目:https://loj.ac/problem/3059 一段 A 选一个 B 的话, B 是这段 A 的平均值.因为 \( \sum (A_i-B)^2 = \sum A_i^2 - 2*B \ ...

  2. 贪心+离散化+线段树上二分。。。 Samara University ACM ICPC 2016-2017 Quarterfinal Qualification Contest G. Of Zorcs and Axes

    题目链接:http://codeforces.com/gym/101149/problem/G 题目大意:给你n对数字,为(a[i], b[i]),给你m对数字,为(w[i], c[i]).给n对数字 ...

  3. 【BZOJ】4293: [PA2015]Siano 线段树上二分

    [题意]给定n棵高度初始为0的草,每天每棵草会长高a[i],m次收割,每次在d[i]天将所有>b[i]的草收割到b[i],求每次收割量.n<=500000. [算法]线段树上二分 [题解] ...

  4. hdu 5930 GCD 线段树上二分/ 强行合并维护信息

    from NOIP2016模拟题28 题目大意 n个点的序列,权值\(<=10^6\) q个操作 1.单点修改 2.求所有区间gcd中,不同数个数 分析 1.以一个点为端点,向左或向右的gcd种 ...

  5. HDU 4747 Mex【线段树上二分+扫描线】

    [题意概述] 一个区间的Mex为这个区间没有出现过的最小自然数,现在给你一个序列,要求求出所有区间的Mex的和. [题解] 扫描线+线段树. 我们在线段树上维护从当前左端点开始的前缀Mex,显然从左到 ...

  6. [NOIP2015模拟10.27] [JZOJ4270] 魔道研究 解题报告(动态开点+权值线段树上二分)

    Description “我希望能使用更多的魔法.不对,是预定能使用啦.最终我要被大家称呼为大魔法使.为此我决定不惜一切努力.”——<The Grimoire of Marisa>雾雨魔理 ...

  7. 【洛谷5537】【XR-3】系统设计(哈希_线段树上二分)

    我好像国赛以后就再也没有写过 OI 相关的博客 qwq Upd: 这篇博客是 NOIP (现在叫 CSP 了)之前写的,但是咕到 CSP 以后快一个月才发表 -- 我最近这么咕怎么办啊 -- 题目 洛 ...

  8. 5.4 省选模拟赛 修改 线段树优化dp 线段树上二分

    LINK:修改 题面就不放了 大致说一下做法.不愧是dls出的题 以前没见过这种类型的 不过还是自己dp的时候写丑了. 从这道题中得到一个结论 dp方程要写的优美一点 不过写的过丑 优化都优化不了. ...

  9. 9 16 模拟赛&关于线段树上二分总结

    1 考试时又犯了一个致命的错误,没有去思考T2的正解而是去简单的推了一下式子开始了漫漫找规律之路,不应该这样做的 为了得到规律虽然也打了暴力 但是还是打了一些不必要的程序 例如求组合数什么的比较浪费时 ...

随机推荐

  1. Redis集群搭建与简单使用【转】

    Redis集群搭建与简单使用 安装环境与版本 用两台虚拟机模拟6个节点,一台机器3个节点,创建出3 master.3 salve 环境. redis 采用 redis-3.2.4 版本. 两台虚拟机都 ...

  2. Eplan P8 2.7 加密狗 感叹号 解决方法

    Eplan安装完加密狗后一直感叹号异常,最近也是查了很多办法,最后发现是少了个驱动的原因. 就是上面这个驱动,这里放上驱动链接:https://lanzous.com/id5gi8f ,或者随便找一个 ...

  3. Docker学习笔记之进入容器Bash

    我们在创建容器的时候,如果容器的命令(command)不是/bin/bash的时候,使用docker attach命令是会卡住进不去容器的bash shell的.如下图所示: 所以,这里记录一个可以进 ...

  4. MyBatis 查询的时候属性名和字段名不一致的问题

    目录 问题 解决方案:resultMap 问题 当我们数据库中的字段和实体类中的字段不一致的时候,查询会出问题 数据库字段是 pwd id name pwd 1 张三 123456 2 李四 1234 ...

  5. leetcode 93. Restore IP Addresses(DFS, 模拟)

    题目链接 leetcode 93. Restore IP Addresses 题意 给定一段序列,判断可能组成ip数的所有可能集合 思路 可以采用模拟或者DFS的想法,把总的ip数分成四段,每段判断是 ...

  6. dmp文件导入抽取方法

    一.确认dmp文件.oracle客户端和服务端的字符集 (1)dmp文件字符集确认: 使用UE打开dmp文件查看文件第2个和第3个字节内容,这两个字节记录了dmp文件的字符集.如0354,然后用以下s ...

  7. 大数据系列2:Hdfs的读写操作

    在前文大数据系列1:一文初识Hdfs中,我们对Hdfs有了简单的认识. 在本文中,我们将会简单的介绍一下Hdfs文件的读写流程,为后续追踪读写流程的源码做准备. Hdfs 架构 首先来个Hdfs的架构 ...

  8. dotnet cli 5.0 新特性——dotnet tool search

    dotnet cli 5.0 新特性--dotnet tool search Intro .NET 5.0 SDK 的发布,给 dotnet cli 引入了一个新的特性,dotnet tool sea ...

  9. 面对key数量多和区间查询低效问题:Hash索引趴窝,LSM树申请出场

    摘要:Hash索引有两个明显的限制:(1)当key的数量很多时,维护Hash索引会给内存带来很大的压力:(2)区间查询很低效.如何对这两个限制进行优化呢?这就轮到本文介绍的主角,LSM树,出场了. 我 ...

  10. (11)-Python3之--os模块

    1.模块介绍 os模块是路径处理模块,它提供了多数操作系统的功能接口函数.当os模块被导入后,它会自适应于不同的操作系统平台,根据不同的平台进行相应的操作,在python编程时,经常和文件.目录打交道 ...