zoukankan      html  css  js  c++  java
  • @bzoj


    @description@

    共有 m 部电影,第 i 部电影的好看值为 w[i]。
    在 n 天之中每天会放映一部电影,第 i 天放映的是第 f[i] 部。
    你可以选择 l, r (1 <= l <= r <= n) ,并观看第 l, l+1, …, r 天内所有的电影。
    最大化观看且仅观看过一次的电影的好看值的总和。

    input
    第一行两个整数 n, m (1 <= m <= n <= 1000000)。
    第二行包含 n 个整数 f[1], f[2], …, f[n](1 <= f[i] <= m)。
    第三行包含 m 个整数 w[1], w[2], …, w[m](1 <= w[j] <= 1000000)。

    output
    输出观看且仅观看过一次的电影的好看值的总和的最大值。

    sample input
    9 4
    2 3 1 1 4 1 2 4 1
    5 3 6 6

    sample output
    15

    @solution@

    和 GSS2 一样的套路啊……

    从左往右扫描每一个点,同时维护一个线段树。
    当扫描到点 i,线段树的每一个点 j 表示以 j 为左端点,i 为右端点的区间权值。

    这样,在扫描的时候维护线段树的最值并作适当的修改,就可以求出答案。

    @accepted code@

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int MAXN = 1000000;
    struct node{
    	int le, ri;
    	ll mx, del;
    }tree[4*MAXN + 5];
    void build(int x, int l, int r) {
    	tree[x].le = l, tree[x].ri = r;
    	tree[x].mx = tree[x].del = 0;
    	if( l == r ) return ;
    	int mid = (l + r) >> 1;
    	build(x<<1, l, mid);
    	build(x<<1|1, mid+1, r);
    }
    void pushdown(int x) {
    	if( tree[x].del ) {
    		tree[x<<1].del += tree[x].del;
    		tree[x<<1].mx += tree[x].del;
    		tree[x<<1|1].del += tree[x].del;
    		tree[x<<1|1].mx += tree[x].del;
    		tree[x].del = 0;
    	}
    }
    void pushup(int x) {
    	tree[x].mx = max(tree[x<<1].mx, tree[x<<1|1].mx);
    }
    void modify(int x, int l, int r, ll val) {
    	if( l > tree[x].ri || r < tree[x].le )
    		return ;
    	if( l <= tree[x].le && tree[x].ri <= r ) {
    		tree[x].del += val, tree[x].mx += val;
    		return ;
    	}
    	pushdown(x);
    	modify(x<<1, l, r, val);
    	modify(x<<1|1, l, r, val);
    	pushup(x);
    }
    ll query(int x, int l, int r) {
    	if( l > tree[x].ri || r < tree[x].le )
    		return -1;
    	if( l <= tree[x].le && tree[x].ri <= r )
    		return tree[x].mx;
    	pushdown(x);
    	return max(query(x<<1, l, r), query(x<<1|1, l, r));
    }
    int f[MAXN + 5], n, m; ll w[MAXN + 5];
    int pre[MAXN + 5], adj[MAXN + 5];
    int main() {
    	ll ans = 0;
    	scanf("%d%d", &n, &m);
    	for(int i=1;i<=n;i++)
    		scanf("%d", &f[i]);
    	for(int i=1;i<=m;i++)
    		scanf("%lld", &w[i]);
    	for(int i=1;i<=n;i++) {
    		pre[i] = adj[f[i]];
    		adj[f[i]] = i;
    	}
    	build(1, 1, n);
    	for(int i=1;i<=n;i++) {
    		if( pre[i] )
    			modify(1, pre[i]+1, i, w[f[i]]), modify(1, pre[pre[i]]+1, pre[i], -w[f[i]]);
    		else modify(1, 1, i, w[f[i]]);
    		ans = max(ans, query(1, 1, i));
    	}
    	printf("%lld
    ", ans);
    }
    

    @details@

    老师让我刷 POI 的题准备在冬令营前给其他人讲解。
    果不其然,他忘记了这件事,我也忘记了这件事。
    嘛……这几天利用零零散散的时间终于大概补齐了 bzoj 上 POI2015 的题目。
    还是有一些思维难度不错的题目,故写一系列博客纪念一下。

    就这道题而言……真的差不多是 GSS2 的套路重现……
    所以应该没什么实现细节。

  • 相关阅读:
    佛学的经典 —— 《妙色王求法偈》
    dom4j的用法
    Android真机网络adb联机调试初探
    CString的部分实现剖析
    文件下载:"Content-disposition","attachment; filename=中文名>>>解决方案
    内存块重叠的判断方法
    闭包
    Twenty Newsgroups Classification任务之二seq2sparse(5)
    IE 加速插件之 Google Chrome Frame
    [Android面试题-7] 写出一个Java的Singleton类(即单例类)
  • 原文地址:https://www.cnblogs.com/Tiw-Air-OAO/p/10353841.html
Copyright © 2011-2022 走看看