zoukankan      html  css  js  c++  java
  • @hdu


    @description@

    给定一个长度为 n 的序列,每一个位置有一个目标颜色,初始所有位置都没有颜色。
    每次操作可以选择一个区间,将这个区间内的位置的颜色改为其目标颜色,代价是区间内不同的目标颜色数量^2。
    求将所有位置改为目标颜色的最小代价。

    Input
    多组数据。
    每组数据第一行一个整数 n(1 ≤ n ≤ 5×10^4),表示序列长度。
    第二行包含 a1,a2,...,an (1 ≤ ai ≤ 10^9 ) 表示每个位置的目标颜色。

    Output
    对于每组数据,输出最小代价。

    Sample Input
    3
    1 3 3
    10
    3 4 2 4 4 2 4 3 2 2
    Sample Output
    2
    7

    @solution@

    不难想到区间不能相交,于是就有一个 O(n^2) 的 dp:dp[i] 表示考虑前 i 位的最小代价,有 dp[i] = min{dp[j] + val(j+1, i)}。

    考虑优化。
    看到代价是平方好像可以斜率,不过仔细一想这个斜率会发生诡异的变化,不行。
    其他优化行不通时考虑决策单调性,好像也不怎么单调。
    其实很简单,没有那么多套路。

    考虑 ans 的一个上界是 n:将所有颜色一个位置一个位置的改变。
    如果区间内的颜色个数 > (sqrt{n}),则代价显然比 ans 的上界还要大,故不合法。于是每一个区间的颜色个数不能超过 (sqrt{n})

    假如以 i 为区间右端点,如果 j 这个位置的颜色在区间 [j+1, i] 出现过,则决策 [j, i] 不会比决策 [j+1, i] 更差。
    这意味着有效的决策点其实只跟每种颜色在 [1, i] 中最后一次出现的位置有关,所以决策点数量只跟区间内所含不同颜色个数有关。

    又因为上面每一个区间的颜色个数不能超过 (sqrt{n}),所以有效决策点的数量也不超过 (sqrt{n})
    用链表维护一下有效决策点即可,时间复杂度 (O(nsqrt{n}))

    @accepted code@

    #include<map>
    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int MAXN = 50000;
    map<int, int>mp;
    int lst[MAXN + 5], nxt[MAXN + 5];
    void link(int x, int y) {
    	nxt[x] = y, lst[y] = x;
    }
    void erase(int x) {
    	nxt[lst[x]] = nxt[x];
    	lst[nxt[x]] = lst[x];
    }
    int a[MAXN + 5], dp[MAXN + 5];
    void solve(int n) {
    	for(int i=1;i<=n;i++)
    		scanf("%d", &a[i]), lst[i] = nxt[i] = -1;
    	mp.clear(); lst[0] = nxt[0] = -1;
    	int sq = sqrt(n);
    	for(int i=1;i<=n;i++) {
    		link(i - 1, i);
    		if( mp.count(a[i]) )
    			erase(mp[a[i]]);
    		mp[a[i]] = i, dp[i] = n;
    		for(int j=1,p=i;j*j<=n&&p;j++,p=lst[p])
    			dp[i] = min(dp[i], dp[lst[p]] + j*j);
    	}
    	printf("%d
    ", dp[n]);
    }
    int main() {
    	int n;
    	while( scanf("%d", &n) == 1 )
    		solve(n);
    }
    

    @details@

    话说这个题看到平方真的很容易往斜率优化那边靠。。。

  • 相关阅读:
    Ace教你一步一步做Android新闻客户端(三) JSON数据解析
    阿冰教你一步一步做Android新闻客户端(二)两种异步线程加载图片的方法
    Android Studio快捷键
    Ace教你一步一步做Android新闻客户端(一)
    Android退出所有Activity最优雅的方式
    Android热门网络框架Volley详解
    Android必学之AsyncTask
    learning scasl notes
    learning armbian steps(11) ----- armbian 源码分析(六)
    am335x system upgrade set/get current cpufreq(二十一)
  • 原文地址:https://www.cnblogs.com/Tiw-Air-OAO/p/11307205.html
Copyright © 2011-2022 走看看