• [Agc029C]Lexicographic constraints_进制_二分答案_贪心


    Lexicographic constraints

    题目链接https://atcoder.jp/contests/agc029/tasks/agc029_c

    数据范围:略。


    题解

    二分是显然的,因为题目具有单调性。

    但是怎么验证呢?

    显然是贪心地验证,就是要$S_i$是满足条件最小的。

    我的办法是维护一棵线段树,因为如果$A_i > A_{i - 1}$的话,只需要在后面加上极小字符。

    然后只需要开一棵动态开点的权值线段树,维护这段区间是不是全是极大字符。如果是的话就不可以再变大了。

    否则的话就可以,修改的话区间修改单点修改。

    但其实不用这么麻烦,我们完全可以用一个$ map $胜任。

    即,我们维护出来相当于一个$ mid $进制的东西。$ map $里存的是每一段的结尾,是什么。前面有一段空挡。

    $ map $是有序的,随便搞一搞就好。

    代码

    #include <bits/stdc++.h>
    
    #define N 200010 
    
    using namespace std;
    
    typedef long long ll;
    
    char *p1, *p2, buf[100000];
    
    #define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )
    
    int rd() {
    	int x = 0, f = 1;
    	char c = nc();
    	while (c < 48) {
    		if (c == '-')
    			f = -1;
    		c = nc();
    	}
    	while (c > 47) {
    		x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
    	}
    	return x * f;
    }
    
    int a[N], n;
    
    map <ll, ll> MP;
    
    bool check(int x) {
    	MP.clear();
    	for (int i = 2; i <= n; i ++ ) {
    		if (a[i - 1] >= a[i]) {
    			if (x == 1) {
    				return false;
    			}
    			while (!MP.empty()) {
    				ll mx = MP.rbegin() -> first;
    				if (mx > a[i]) {
    					MP.erase(mx);
    				}
    				else {
    					break;
    				}
    			}
    
    			int j = a[i];
    			while (j > 0 && MP[j] + 1 == x) {
    				MP.erase(j);
    				j -- ;
    			}
    			if (!j) {
    				return false;
    			}
    			MP[j] ++ ;
    		}
    	}
    	return true;
    }
    
    
    int main() {
    	n = rd();
    	for (int i = 1; i <= n; i ++ ) {
    		a[i] = rd();
    	}
    
    	int l = 1, r = n, ans = n;
    	while (l <= r) {
    		int mid = (l + r) >> 1;
    		if (check(mid)) {
    			ans = mid;
    			r = mid - 1;
    		}
    		else {
    			l = mid + 1;
    		}
    	}
    	cout << ans << endl ;
    	return 0;
    }
    
  • 相关阅读:
    反转链表
    linux shell 读取配置文件的一个例子
    python 笔记碎片
    工作笔记整理
    linux服务器之间文件互传
    工作软件收集
    linux同步时间
    利用linux的df和du命令查看文件和目录的内存占用
    windows常用快捷键
    SUSE 12 安装 python3.6
  • 原文地址:https://www.cnblogs.com/ShuraK/p/11734650.html
Copyright © 2020-2023  润新知