码迷,mamicode.com
首页 > 其他好文 > 详细

AT3673 NRE

时间:2019-07-17 19:14:17      阅读:107      评论:0      收藏:0      [点我收藏+]

标签:include   eof   ==   sdi   mat   mod   const   lse   最小   

化简一下题意:其实就是求:
\(\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;  
}

AT3673 NRE

标签:include   eof   ==   sdi   mat   mod   const   lse   最小   

原文地址:https://www.cnblogs.com/Sai0511/p/11202625.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!