zoukankan      html  css  js  c++  java
  • ICPC2020上海站F Fountains 状压

    题意:给定长为(n)的序列,定义区间([l,r])的权值(C(l,r))([l,r])中所有元素的和,现在试选择(k)个区间([l_i, r_i](1leq l_ileq r_ileq n)),使得
    $$sum_{1leq Lleq Rleq n} [C(L, R) - max_{Lleq l_i leq r_i leq R } C(l_i, r_i)]$$最小,对(k=1, 2, 3..., n*(n+1)/2)作出回答,且(nleq 9)


    不妨假定已经选择(k)个区间,考虑怎么使得权值和最小

    显然,将(k)个区间按权值大小从大到小排序,所有的([L, R])区间会按此顺序选择第一个被它包含的区间([l_i, r_i])

    换而言之,即将(k)个区间从大到小排序后,依次考虑,在仍未选择的区间([L, R])中,所有能选择([l_i, r_i])的区间一定会选择此区间

    可以(dp),状态为已经选择了(k)个区间,及仍未选择的区间

    仍未选择的区间可以通过((r_1, r_2, ..., r_n))表示,其中(r_i)表示([i, i], [i,i+1], ..., [i, r_i])仍未选择

    由于(r_1leq r_2 leq ... leq r_n),状态数并不大(最大375544),并且本题有6s时限,hash都不用,开个map即可过

    #include <map>
    #include <vector>
    #include <cstdio>
    #include <iostream>
    #include <algorithm> 
    using namespace std;
    
    #define l first
    #define r second
    #define ll long long
    #define mp make_pair
    #define pii pair <int, int>
    #define rep(io, st, ed) for(int io = st; io <= ed; io ++)
    #define drep(io, ed, st) for(int io = ed; io >= st; io --)
    
    const int sid = 1e6 + 5;
    
    int n, tt[105];
    ll all, ans[105], s[105];
    map <ll, ll> now, pre;
    vector <pii> seg;
    
    ll encode(int *a) {
    	ll ret = 0;
    	drep(i, n + 1, 1) ret = ret * 10 + a[i];
    	return ret;
    }
    
    void decode(ll v, int *a) {
    	rep(i, 1, n) a[i] = v % 10, v /= 10;
    	a[n + 1] = v;
    }
    
    int main() {
    	cin >> n;
    	rep(i, 1, n) cin >> s[i], s[i] += s[i - 1];
    	rep(L, 1, n) rep(R, L, n) seg.push_back(mp(L, R)), all += s[R] - s[L - 1];
    	sort(seg.begin(), seg.end(), [](pii &a, pii &b) { return s[a.r] - s[a.l - 1] >= s[b.r] - s[b.l - 1]; } );
    	rep(i, 1, n) tt[i] = n; now[encode(tt)] = 0;
    	rep(si, 0, seg.size() - 1) {
    		int l = seg[si].l, r = seg[si].r;
    		ll v = s[r] - s[l - 1];
    		pre = now; now.clear();
    		for(auto x : pre) {
    			ll pv = x.second; decode(x.first, tt);
    			//不选择
    			now[x.first] = max(now[x.first], pv);
    			//选择
    			rep(i, 1, l) if(tt[i] >= r) pv += (tt[i] - r + 1) * v, tt[i] = r - 1;
    			tt[n + 1] ++; ll to = encode(tt);
    			now[to] = max(now[to], pv);
    		}
    	}
    	for(auto x : now) {
    		decode(x.first, tt);
    		ans[ tt[n + 1] ] = max(ans[ tt[n + 1] ], x.second);
    	}
    	rep(i, 1, n * (n + 1) / 2) printf("%lld
    ", all - ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    topcoder srm 320 div1
    topcoder srm 325 div1
    topcoder srm 330 div1
    topcoder srm 335 div1
    topcoder srm 340 div1
    topcoder srm 300 div1
    topcoder srm 305 div1
    topcoder srm 310 div1
    topcoder srm 315 div1
    如何统计iOS产品不同渠道的下载量?
  • 原文地址:https://www.cnblogs.com/reverymoon/p/14153891.html
Copyright © 2011-2022 走看看