• 【USACO 2021 February Contest, Platinum】Problem 1 No Time to Dry


    ( ext{Solution})

    一个点可与另一个颜色相同点同时涂色当且仅当两点间颜色都大于等于这两点
    那么我们可以预处理一个点向左向右最远能到的位置,记为 (l_i,r_i))
    (l_i = l_j ext{ and }r_i = r_j) 时,((i,j)) 就可以同时涂色
    我们认为他们是相同
    预处理 (l_i,r_i) 正反两次单调栈即可

    那么一个区间的答案就是 (l_i,r_i) 不相同的个数
    (l_i,r_i) 排序后重新编号,主席树维护即可
    这就相当于区间数颜色
    注:空间开到 (2 log n)
    纪念考场暴切此题但空间开小白丢 (5pts)

    #include <cstdio> 
    #include <algorithm>
    #include <cstring>
    #define re register
    using namespace std;
    
    const int N = 2e5 + 5;
    int n, q, stk[N], top;
    struct node{int v, l, r, id;}a[N];
    
    inline void read(int &x)
    {
    	x = 0; char ch = getchar();
    	while (ch < '0' || ch > '9') ch = getchar();
    	while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
    }
    
    inline bool cmp1(node a, node b){return (a.l < b.l ? 1 : (a.l == b.l ? a.r < b.r : 0));}
    inline bool cmp2(node a, node b){return a.id < b.id;}
    
    int size, lst[N], rt[N];
    struct ChairManTree{int ls, rs, s;}seg[N * 40];
    inline void update(int &p, int pre, int l, int r, int x, int v)
    {
    	p = ++size;
    	seg[p] = seg[pre], seg[p].s = seg[pre].s + v;
    	if (l == r) return;
    	int mid = (l + r) >> 1;
    	if (x <= mid) update(seg[p].ls, seg[pre].ls, l, mid, x, v);
    	else update(seg[p].rs, seg[pre].rs, mid + 1, r, x, v);
    }
    inline int query(int p, int l, int r, int x)
    {
    	if (l == r) return seg[p].s;
    	int mid = (l + r) >> 1;
    	if (x <= mid) return query(seg[p].ls, l, mid, x) + seg[seg[p].rs].s;
    	return query(seg[p].rs, mid + 1, r, x);
    }
    
    int main()
    {
    	read(n), read(q);
    	for(re int i = 1; i <= n; i++) read(a[i].v), a[i].l = a[i].r = a[i].id = i;
    	for(re int i = 1; i <= n; i++)
    	{
    		while (top && a[stk[top]].v >= a[i].v) a[i].l = a[stk[top]].l, --top;
    		if (!top) a[i].l = 1;
    		stk[++top] = i;
    	}
    	top = 0;
    	for(re int i = n; i; i--)
    	{
    		while (top && a[stk[top]].v >= a[i].v) a[i].r = a[stk[top]].r, --top;
    		if (!top) a[i].r = n;
    		stk[++top] = i;
    	}
    	
    	sort(a + 1, a + n + 1, cmp1);
    	a[1].v = top = 1;
    	for(re int i = 2; i <= n; i++)
    	if (a[i].l == a[i - 1].l && a[i].r == a[i - 1].r) a[i].v = top;
    	else a[i].v = ++top;
    	sort(a + 1, a + n + 1, cmp2);
    	
    	memset(lst , 255 , sizeof lst);
    	for(re int i = 1, pre; i <= n; i++) 
    	{
    		if (lst[a[i].v] == -1) update(rt[i], rt[i - 1], 1, n, i, 1);
    		else update(pre, rt[i - 1], 1, n, lst[a[i].v], -1), update(rt[i], pre, 1, n, i, 1);
    		lst[a[i].v] = i;
    	}
    	for(re int i = 1, l, r; i <= q; i++)
    		read(l), read(r), printf("%d
    ", query(rt[r], 1, n, l));
    }
    
  • 相关阅读:
    Linux内核空间-用户空间通信之debugfs
    Mysql 启动失败 报错 1067
    [置顶] hdu3018解题报告--也是白话几笔画学习总结
    【Todo】蒙特卡洛(蒙特卡罗)树 & 卷积网络
    基本分类方法——KNN(K近邻)算法
    SVM(支持向量机)与统计机器学习 & 也说一下KNN算法
    可重入锁 & 自旋锁 & Java里的AtomicReference和CAS操作 & Linux mutex不可重入
    【Todo】Nginx架构学习
    【转载】C++异常机制的学习
    关于协程的学习 & 线程栈默认10M
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/15148810.html
Copyright © 2020-2023  润新知