当前位置: 首页 > article >正文

P9993 [Ynoi Easy Round 2024] TEST_133 Solution

Description

给定序列 a = ( a 1 , a 2 , ⋯   , a n ) a=(a_1,a_2,\cdots,a_n) a=(a1,a2,,an) b b b(初始为 a a a),有 m m m 个操作分两种:

  • add ⁡ ( l , r , x ) \operatorname{add}(l,r,x) add(l,r,x):对每个 i ∈ [ l , r ] i \in [l,r] i[l,r] 执行 a i ← a i + x a_i \gets a_i+x aiai+x.
  • query ⁡ ( l , r , x ) \operatorname{query}(l,r,x) query(l,r,x):求 max ⁡ i ∈ [ l , r ] , a i < x b i \max\limits_{i\in [l,r],a_i < x} b_i i[l,r],ai<xmaxbi,若没有满足的 i i i 输出 − ∞ -\infty .

每次操作后,对每个 i ∈ [ 1 , n ] i \in [1,n] i[1,n] 执行 b i ← max ⁡ ( a i , b i ) b_i \gets \max(a_i,b_i) bimax(ai,bi).

Limitations

1 ≤ n , m ≤ 5 × 1 0 5 1 \le n,m \le 5\times 10^5 1n,m5×105
∣ a i ∣ , ∣ x ∣ ≤ 1 0 9 |a_i|,|x| \le 10^9 ai,x109
40 s , 512 MB \textcolor{red}{40\text{s}},512\text{MB} 40s,512MB

Solution

发现线段树不能维护,考虑分块.
维护 a i a_i ai 和其历史最大值 hist i \textit{hist}_i histi.
对于每个块,维护块内 a i a_i ai 排序后结果 p i p_i pi,排序后 b i b_i bi 前缀和 h p r e i hpre_i hprei a i a_i ai 加标记 add \textit{add} add b i b_i bi 加标记 hadd \textit{hadd} hadd.
下传标记及修改仿照吉司机就行,查询时散块暴力,整块二分.
时间复杂度 O ( ( n + m ) n log ⁡ n ) O((n+m)\sqrt{n}\log{n}) O((n+m)n logn),时限很大所以能过.

Code

4.05 KB , 3.67 min , 23.41 MB    (in   total,   C++   with   O2) 4.05\text{KB},3.67\text{min},23.41\text{MB}\;\texttt{(in total, C++ with O2)} 4.05KB,3.67min,23.41MB(in total, C++ with O2)

// Problem: P9993 [Ynoi Easy Round 2024] TEST_133
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P9993
// Memory Limit: 512 MB
// Time Limit: 40000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;

using i64 = long long;
using ui64 = unsigned long long;
using i128 = __int128;
using ui128 = unsigned __int128;
using f4 = float;
using f8 = double;
using f16 = long double;

template<class T>
bool chmax(T &a, const T &b){
	if(a < b){ a = b; return true; }
	return false;
}

template<class T>
bool chmin(T &a, const T &b){
	if(a > b){ a = b; return true; }
	return false;
}

const i64 inf = 3e18;
struct Block {
    int n, B, blocks;
    vector<int> belong, L, R, id;
    vector<i64> a, hist, hpre, add, hadd, p;
    
    inline Block() {}
    inline Block(const vector<i64>& a) {
        this->a = a;
        this->hist = a;
        n = a.size();
        B = sqrt(n);
        blocks = n / B + (n % B > 0);
        
        belong.resize(n);
        L.resize(blocks);
        R.resize(blocks);
        hpre.resize(n);
        add.resize(blocks);
        hadd.resize(blocks);
        id.resize(n);
        p.resize(n);
        
        for (int i = 0; i < blocks; i++) {
            L[i] = i * B;
            R[i] = min(L[i] + B - 1, n - 1);
            for (int j = L[i]; j <= R[i]; j++) belong[j] = i;
            rebuild(i);
        }
    }
    
    inline void pushdown(int u) {
        for (int i = L[u]; i <= R[u]; i++) {
            hist[i] = max(hist[i], a[i] + hadd[u]);
            a[i] += add[u];
        }
        add[u] = hadd[u] = 0;
    }
    
    inline void rebuild(int u) {        
        iota(id.begin() + L[u], id.begin() + R[u] + 1, L[u]);
        sort(id.begin() + L[u], id.begin() + R[u] + 1, [&](int x, int y) {
            return a[x] < a[y];
        });
        
        for (int i = L[u]; i <= R[u]; i++) p[i] = a[id[i]];
        hpre[L[u]] = hist[id[L[u]]];
        for (int i = L[u] + 1; i <= R[u]; i++) hpre[i] = max(hpre[i - 1], hist[id[i]]);
    }
    
    inline void brute_modify(int l, int r, int k) {
        pushdown(belong[l]);
        for (int i = l; i <= r; i++) {
            a[i] += k;
            hist[i] = max(hist[i], a[i]);
        }
        rebuild(belong[l]);
    }
    
    inline void modify(int l, int r, int k) {
        if (belong[l] == belong[r]) return brute_modify(l, r, k);
        brute_modify(l, R[belong[l]], k);
        for (int i = belong[l] + 1; i < belong[r]; i++) {
            add[i] += k;
            hadd[i] = max(hadd[i], add[i]);
        }
        brute_modify(L[belong[r]], r, k);
    }
    
    inline i64 brute_query(int l, int r, int k) {
        i64 ans = -inf;
        for (int i = l; i <= r; i++) {
            if (a[i] + add[belong[i]] < k) {
                ans = max(ans, hist[i]);
                ans = max(ans, a[i] + hadd[belong[i]]);
            }
        }
        return ans;
    }
    
    inline i64 query(int l, int r, int k) {
        if (belong[l] == belong[r]) return brute_query(l, r, k);
        i64 ans = brute_query(l, R[belong[l]], k);
        for (int i = belong[l] + 1; i < belong[r]; i++) {
            auto it = lower_bound(p.begin() + L[i], p.begin() + R[i] + 1, k - add[i]) - 1;
            if (p.begin() + L[i] <= it) {
                ans = max(ans, hpre[it - p.begin()]);
                ans = max(ans, *it + hadd[i]);
            }
        }
        ans = max(ans, brute_query(L[belong[r]], r, k));
        return ans;
    }
};

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	
	int n, m;
	scanf("%d %d", &n, &m);
	
	vector<i64> a(n);
	for (int i = 0; i < n; i++) scanf("%lld", &a[i]);
	
	Block blk(a);
	for (int i = 0, op, l, r, k; i < m; i++) {
	    scanf("%d %d %d %d", &op, &l, &r, &k);
	    l--, r--;
	    
	    if (op == 1) blk.modify(l, r, k);
	    else {
	        i64 ans = blk.query(l, r, k);
	        if (ans == -inf) printf("-inf\n");
	        else printf("%lld\n", ans);
	    }
	}
	
	return 0;
}

http://www.kler.cn/a/547453.html

相关文章:

  • Rust包管理
  • Vue学习笔记4
  • 循环队列知识点及习题
  • C++从入门到实战(四)C++引用与inline,nullptr
  • 青少年编程与数学 02-009 Django 5 Web 编程 13课题、URL分发
  • 【Java 面试 八股文】Spring Cloud 篇
  • 【认证授权FAQ】SSL/TLS证书过期导致的CLS认证失败
  • 联想笔记本电脑摄像头灯亮,但没有画面怎么解决,
  • Python的那些事第二十一篇:Python Web开发的“秘密武器”Flask
  • MATLAB图像处理:图像特征概念及提取方法HOG、SIFT
  • 将Sqlite3数据库挂在内存上处理
  • 老游戏回顾:GOWpsp
  • 【网络安全 | 漏洞挖掘】后端接受非预期参数的故事
  • pgAdmin 4 启动 PSQL Tool
  • export关键字
  • 基于深度学习的消费物联网中安全音乐流量传输方法
  • ROS2服务通信与通信接口
  • 嵌入式 Linux 驱动开发:点灯大法
  • 【Java】ArrayList与LinkedList的性能对比深度解析
  • 探秘 Map 和 Set 底层:二叉搜索树与哈希表的深度解析,解锁高效数据存储秘密!