• 【HEOI2016】序列


    题面

    题解

    很像最长不下降子序列对吧(废话)

    设$up[i]$和$down[i]$分别表示$i$最大最小能取多少

    注意到:

    $$ f[i] = max_jleft{f[j] ight} + 1 \ a[j] leq down[i],; up[j] leq a[i],; j leq i $$

    三位偏序!!!

    $CDQ$分治走起

    代码

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #define RG register
    
    inline int read()
    {
    	int data = 0, w = 1; char ch = getchar();
    	while(ch != '-' && (!isdigit(ch))) ch = getchar();
    	if(ch == '-') w = -1, ch = getchar();
    	while(isdigit(ch)) data = data * 10 + (ch ^ 48), ch = getchar();
    	return data * w;
    }
    
    using std::max;
    const int maxn(100010);
    int n, m, a[maxn], up[maxn], down[maxn], c[maxn], f[maxn], Max;
    inline bool cmp_1(int x, int y) { return a[x] < a[y]; }
    inline bool cmp_2(int x, int y) { return down[x] < down[y]; }
    void clean(int x) { while(x <= Max) c[x] = 0, x += x & -x; }
    void add(int x, int v) { while(x <= Max) c[x] = max(c[x], v), x += x & -x; }
    int query(int x)
    {
    	int ans = 0;
    	while(x) ans = max(ans, c[x]), x -= x & -x;
    	return ans;
    }
    
    void Div(int l, int r)
    {
    	static int id[maxn];
    	if(l == r) return (void)(f[l] = max(f[l], 1));
    	int mid = (l + r) >> 1; Div(l, mid);
    	for(RG int i = l; i <= r; i++) id[i] = i;
    	std::sort(id + l, id + mid + 1, cmp_1);
    	std::sort(id + mid + 1, id + r + 1, cmp_2);
    	int j = l;
    	for(RG int i = mid + 1; i <= r; i++)
    	{
    		while(j <= mid && a[id[j]] <= down[id[i]]) add(up[id[j]], f[id[j]]), j++;
    		f[id[i]] = max(f[id[i]], query(a[id[i]]) + 1);
    	}
    	for(RG int i = l; i < j; i++) clean(up[id[i]]);
    	Div(mid + 1, r);
    }
    
    int main()
    {
    	n = read(), m = read();
    	for(RG int i = 1; i <= n; i++) up[i] = down[i] = a[i] = read();
    	for(RG int i = 1, x, y; i <= m; i++)
    		x = read(), y = read(),
    		  up[x] = max(up[x], y),
    		  down[x] = std::min(down[x], y);
    	Max = *std::max_element(up + 1, up + n + 1);
    	Div(1, n); printf("%d
    ", *std::max_element(f + 1, f + n + 1));
    	return 0;
    }
    
  • 相关阅读:
    AGC005D ~K Perm Counting
    运行python脚本后台执行
    java枚举类型
    java可变参数长度
    java 泛型数组列表
    java抽象类
    java final使用
    java继承
    java 对象
    java 重载
  • 原文地址:https://www.cnblogs.com/cj-xxz/p/10247095.html
Copyright © 2020-2023  润新知