zoukankan      html  css  js  c++  java
  • AT3673 NRE

    化简一下题意:其实就是求:
    (sum_{i = 1}^n [a0b1] + sum_{i = 1}^n [a1b0])
    其实就等于(sum_{i = 1}^n [a0b1] + sum_{i = 1}^n[b0] - sum_{i = 1}^n[a0b0]),其实现在已经和(a1)没关系了,这里的(b0)也可以直接算出来。
    接着我们想一个(dp),(dp_i)表示前(i)个数中(a0b1 - a1b0)的最小值。
    我们把所有区间排个序,
    然后考虑一下选与不选这个区间的情况,
    因为选了都为(1),而现在已经和(1)没有关系了,所以可以理解为从(i - 1 sim j)这里跳过来,取个最小值,这里可以用线段树来优化。
    而不选其实就是(dp[i - 1] + (!b[i] ? -1 : 1)),因为前面推的(dp)的公式是(a0b1 - a1b0)
    然后就做完了,代码感觉挺好写的样子。

    #include <bits/stdc++.h>
     
    const int maxn = 2e5 + 10;
    const int inf = 0x3f3f3f3f;
     
    int n, m, i, j, k, cnt0, dp[maxn];    
    int a[maxn], b[maxn], t[maxn << 2];
    std::vector<int> v[maxn];   
     
    inline int _max(int a,int b) { return a > b ? a : b; }
    inline int _min(int a,int b) { return a < b ? a : b; }  
    inline void cmin(int& a,int b) {
        if(a > b)
            a = b;   
    }
     
    template<class t> inline void read(t& res) {
        res = 0;  char ch = getchar();  bool sign = 0;
        while(!isdigit(ch))  
            sign |= ch == '-', ch = getchar();
        while(isdigit(ch))
            res = (res << 1) + (res << 3) + (ch & 15), ch = getchar();
        if(sign)
            res = -res;
    }
     
    inline int f(int x) {
        return x == 1 ? 1 : -1;   
    }
     
    void build(int l,int r,int u) {
        t[u] = inf;
        if(l == r)
            return;
        int mid = (l + r) >> 1;
        build(l,mid,u << 1);
        build(mid + 1,r,u << 1 | 1);   
    }
    inline void push_up(int u) {
        t[u] = _min(t[u << 1],t[u << 1 | 1]);
    }
    void modify(int M,int l,int r,int u,int v) {   
        if(l == r)
            return cmin(t[u],v), void();  
        int mid = (l + r) >> 1;
        if(M <= mid)
            modify(M,l,mid,u << 1,v);
        else
            modify(M,mid + 1,r,u << 1 | 1,v);
        push_up(u); 
    }
    int query(int ql,int qr,int l,int r,int u) {    
        if(ql <= l && r <= qr)
            return t[u];
        int res = inf, mid = (l + r) >> 1;  
        if(ql <= mid)
            cmin(res,query(ql,qr,l,mid,u << 1));
        if(mid < qr)
            cmin(res,query(ql,qr,mid + 1,r,u << 1 | 1));
        return res;     
    }
     
    int main() {
        read(n);  
        memset(dp,0x3f,sizeof(dp));   
        for(int i = 1;i <= n;i++)
            read(b[i]), cnt0 += b[i] ^ 1;
        build(1,n,1);
        read(m);
        for(int i = 1, l, r;i <= m;i++) 
            read(l), read(r), v[l].push_back(r);
        dp[0] = 0;                 
        for(int i = 1;i <= n;i++) {
            int sz = v[i].size();
            for(int j = 0;j < sz;j++) {
                int x = v[i][j], mn = dp[i - 1];     
                cmin(mn, query(_max(i - 1,1),x,1,n,1));
                if(mn < dp[x])
                    dp[x] = mn, modify(x,1,n,1,mn);   
            }
            cmin(dp[i],dp[i - 1] + f(b[i]));
        }
        printf("%d",dp[n] + cnt0);
        return 0;  
    }
    
  • 相关阅读:
    实例讲解Springboot以Repository方式整合Redis
    Spark join 源码跟读记录
    数理统计与参数估计杂记
    常见的距离算法和相似度(相关系数)计算方法
    生成模型(Generative Model)与判别模型(Discriminative Model)
    Java 积累复习用
    RangePartitioner 实现简记
    Spark常见问题汇总
    2016年终总结
    学习资料库
  • 原文地址:https://www.cnblogs.com/Sai0511/p/11202625.html
Copyright © 2011-2022 走看看