化简一下题意:其实就是求:
\(\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;  
}
优质内容筛选与推荐>>
1、ARM-Linux驱动--DM9000网卡驱动分析(二)
2、jquery.validate验证text,checkbox,radio,selected
3、[教程]使用Lite MP4 Tool专业制作MP4(AVC)视频格式 - 指导教程
4、navicat连接不上Linux服务器上的MySQL
5、网站前台的三级联动数据封装


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号