zoukankan      html  css  js  c++  java
  • 【LG3582】[POI2015]KIN

    【LG3582】[POI2015]KIN

    题面

    洛谷

    题解

    这题维护区间的信息有点像最大子段和,我们往最大子段和上面靠。

    对于一个颜色,我们有一个直观的想法就是将它一次出现的权值设为正,二次出现就设为负。

    但是当区间中出现次数多于两次怎么办呢?我们可以考虑从左往右扫这个序列,这个数出现在最靠右的位置时设权值为正,第二靠右出现时设权值为负,否则全部设为0,这样子的话,我们用最大子段和维护就行了。就算你只访问到一个负的权值也没关系,因为你在前面已经把这种情况的答案算进去了。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring> 
    #include <cmath> 
    #include <algorithm>
    using namespace std; 
    inline int gi() {
        register int data = 0, w = 1;
        register char ch = 0;
        while (!isdigit(ch) && ch != '-') ch = getchar(); 
        if (ch == '-') w = -1, ch = getchar(); 
        while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); 
        return w * data; 
    } 
    const int MAX_N = 1e6 + 5; 
    #define lson (o << 1) 
    #define rson (o << 1 | 1) 
    struct Node { long long ls, rs, ms, ss; } t[MAX_N << 2]; 
    void pushup(int o) { 
    	t[o].ms = t[lson].ms + t[rson].ms; 
    	t[o].ls = max(t[lson].ms + t[rson].ls, t[lson].ls); 
    	t[o].rs = max(t[rson].ms + t[lson].rs, t[rson].rs); 
    	t[o].ss = max(max(t[lson].ss, t[rson].ss), t[lson].rs + t[rson].ls); 
    } 
    void modify(int o, int l, int r, int pos, int v) { 
    	if (l == r) return (void)(t[o] = (Node){v, v, v, v}); 
    	int mid = (l + r) >> 1; 
    	if (pos <= mid) modify(lson, l, mid, pos, v); 
    	else modify(rson, mid + 1, r, pos, v); 
    	pushup(o); 
    } 
    int N, M, a[MAX_N], w[MAX_N]; 
    int pre[MAX_N], lst[MAX_N]; 
    int main () {
    #ifndef ONLINE_JUDGE 
        freopen("cpp.in", "r", stdin);
    #endif 
    	N = gi(), M = gi(); 
    	for (int i = 1; i <= N; i++) a[i] = gi(); 
    	for (int i = 1; i <= M; i++) w[i] = gi(); 
    	long long ans = 0; 
    	for (int i = 1; i <= N; i++) { 
    		pre[i] = lst[a[i]], lst[a[i]] = i; 
    		if (pre[i]) modify(1, 1, N, pre[i], -w[a[i]]); 
    		if (pre[pre[i]]) modify(1, 1, N, pre[pre[i]], 0); 
    		modify(1, 1, N, i, w[a[i]]); 
    		ans = max(ans, t[1].ss); 
    	} 
    	printf("%lld
    ", ans); 
        return 0; 
    } 
    
  • 相关阅读:
    SpringBoot学习
    Matlab立体标定mat转换成Opencv的CvMat
    由lib引发的血案(opencv找不函数问题)
    C# 使用Epplus导出Excel [4]:合并指定行
    C# 使用Epplus导出Excel [3]:合并列连续相同数据
    C# 使用Epplus导出Excel [2]:导出动态列数据
    C# 使用Epplus导出Excel [1]:导出固定列数据
    C# Excel常用控件总结
    C# IsNullOrEmpty与IsNullOrWhiteSpace
    C# 读App.config配置文件[2]: .Net Core框架
  • 原文地址:https://www.cnblogs.com/heyujun/p/11711486.html
Copyright © 2011-2022 走看看