zoukankan      html  css  js  c++  java
  • 【LOJ】#2275. 「JXOI2017」颜色

    题解

    我们枚举右端点判断合法的左端点有哪些

    首先,记录一下右端点右边的点的pre,也就是这个数字前一个出现的位置,取所有小于枚举右端点r的值中最大的一个做为l,用优先队列维护即可,[l + 1,r]就是可能取到的左端点的区间

    然后我们对于每一种数字,最前一次出现的位置p,最后一次出现的位置q,覆盖[p + 1,q]这段区间作为不能填的区间,用线段树维护一下,用可取的左端点区间减掉不能填的地方

    如果右端点出现过了,那么删除这种数字的覆盖区间,可以在右端点左移的时候同时干这件事

    代码

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <set>
    #include <cmath>
    #include <bitset>
    #include <queue>
    #define enter putchar('
    ')
    #define space putchar(' ')
    //#define ivorysi
    #define pb push_back
    #define mo 974711
    #define pii pair<int,int>
    #define mp make_pair
    #define fi first
    #define se second
    #define MAXN 200005
    using namespace std;
    typedef long long int64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 - '0' + c;
    	c = getchar();
        }
        res = res * f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) out(x / 10);
        putchar('0' + x % 10);
    }
    int N;
    int a[MAXN],minn[MAXN],maxx[MAXN],pre[MAXN],last[MAXN],vis[MAXN];
    int64 ans;
    priority_queue<int> Q;
    struct node {
        int l,r,cover,sum;
    }tr[MAXN * 4];
    void build(int u,int l,int r) {
        tr[u].l = l;tr[u].r = r;
        tr[u].cover = 0;tr[u].sum = 0;
        if(l == r) return;
        int mid = (l + r) >> 1;
        build(u << 1,l,mid);
        build(u << 1 | 1,mid + 1,r);
    }
    void addcover(int u,int v) {
        tr[u].cover += v;
        if(tr[u].cover) tr[u].sum = tr[u].r - tr[u].l + 1;
        else tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
    }
    void update(int u) {
        if(tr[u].cover) tr[u].sum = tr[u].r - tr[u].l + 1;
        else tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
    }
    void Add(int u,int l,int r,int on) {
        if(l > r) return;
        if(tr[u].l == l && tr[u].r == r) {
    	addcover(u,on);
    	return;
        }
        int mid = (tr[u].l + tr[u].r) >> 1;
        if(r <= mid) Add(u << 1,l,r,on);
        else if(l > mid) Add(u << 1 | 1,l,r,on);
        else Add(u << 1,l,mid,on),Add(u << 1 | 1,mid + 1,r,on);
        update(u);
    }
    int Query(int u,int l,int r) {
        if(tr[u].cover) return r - l + 1;
        if(tr[u].l == l && tr[u].r == r) return tr[u].sum;
        int mid = (tr[u].l + tr[u].r) >> 1;
        if(r <= mid) return Query(u << 1,l,r);
        else if(l > mid) return Query(u << 1 | 1,l,r);
        else return Query(u << 1,l,mid) + Query(u << 1 | 1,mid + 1,r);
    }
    void Solve() {
        while(!Q.empty()) Q.pop();
        read(N);
        build(1,1,N);
        ans = 0;
        for(int i = 1 ; i <= N ; ++i) {
    	read(a[i]);
    	minn[i] = N;maxx[i] = 0;
    	pre[i] = 0;last[i] = 0;
        }
        for(int i = 1 ; i <= N ; ++i) {
    	minn[a[i]] = min(minn[a[i]],i);
    	maxx[a[i]] = max(maxx[a[i]],i);
        }
        for(int i = 1 ; i <= N ; ++i) {
    	if(!vis[a[i]]) {
    	    Add(1,minn[a[i]] + 1,maxx[a[i]],1);
    	    vis[a[i]] = 1;
    	}
        }
        for(int i = 1 ; i <= N ; ++i) {
    	pre[i] = last[a[i]];
    	last[a[i]] = i;
        }
        Q.push(0);
        for(int i = N ; i >= 1 ; --i) {
    	while(Q.top() > i) Q.pop();
    	int L = Q.top() + 1;
    	if(L <= i) {
    	    int t = i - L + 1;
    	    ans += t - Query(1,L,i);
    	}
    	Q.push(pre[i]);
    	if(vis[a[i]]) {
    	    Add(1,minn[a[i]] + 1,maxx[a[i]],-1);
    	    vis[a[i]] = 0;
    	}
        }
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        int T;
        read(T);
        while(T--) {
    	Solve();
        }
    }
    
  • 相关阅读:
    gcc编译代码报错及编译方式
    YUV到RGB的转换
    YUV和RGB格式分析
    v4l2的学习建议和流程解析
    在Ubuntu下安装imx6linux系统的交叉编译环境遇到的问题总结
    《赢在测试2》--读书笔记
    关于javascript的slice方法
    数字的千分位格式化方法
    javascript开发中的封装模式(转)
    防止表单重复提交的几种方法
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9200644.html
Copyright © 2011-2022 走看看