zoukankan      html  css  js  c++  java
  • BZOJ 3747: [POI2015]Kinoman

    考虑枚举起点,找一个最远的右端点使得以这个点为起点的答案最大

    用线段树维护,需要设计一种标记,使得含有多个数的前缀中减去这个数的贡献

    考虑这样设计,对于第一次出现的数,对其赋值$w[i]$

    第二次出现 赋值$-w[i]$

    第三次出现 赋值为0

    这样前缀和就满足多次出现的数不会计算贡献

    再维护前驱节点和后驱节点,每次删去开头的数,维护一下后驱节点

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 #define N 1000010
     6 #define INF 0x3f3f3f3f3f3f3f3f
     7 int n, m, f[N], pre[N], nx[N];
     8 ll w[N], v[N];
     9 map <int, int> mp;
    10 
    11 namespace SEG
    12 {
    13     ll Max[N << 2], lazy[N << 2];
    14     void init()
    15        { 
    16         memset(Max, 0, sizeof Max);
    17         memset(lazy, 0, sizeof lazy);   
    18     }
    19     void pushdown(int id)
    20     {
    21         if (!lazy[id]) return;
    22         lazy[id << 1] += lazy[id];
    23         Max[id << 1] += lazy[id];
    24         lazy[id << 1 | 1] += lazy[id];
    25         Max[id << 1 | 1] += lazy[id]; 
    26         lazy[id] = 0;
    27     }
    28     void update(int id, int l, int r, int ql, int qr, ll val)
    29     {
    30         if (l >= ql && r <= qr) 
    31         {
    32             lazy[id] += val;
    33             Max[id] += val;
    34             return;
    35         }
    36         pushdown(id); 
    37         int mid = (l + r) >> 1;
    38         if (ql <= mid) update(id << 1, l, mid, ql, qr, val);
    39         if (qr > mid) update(id << 1 | 1, mid + 1, r, ql, qr, val);
    40         Max[id] = max(Max[id << 1], Max[id << 1 | 1]); 
    41     }
    42 }
    43 
    44 int main()
    45 {
    46     while (scanf("%d%d", &n, &m) != EOF)
    47     {
    48         for (int i = 1; i <= n; ++i) scanf("%d", f + i);
    49         for (int i = 1; i <= m; ++i) scanf("%lld", w + i);
    50         mp.clear();
    51         for (int i = 1; i <= n; ++i)
    52         {
    53             if (mp.find(f[i]) != mp.end())
    54                 pre[i] = mp[f[i]];
    55             else
    56                 pre[i] = 0;
    57             mp[f[i]] = i;
    58         }
    59         mp.clear(); 
    60         for (int i = n; i >= 1; --i)
    61         {
    62             if (mp.find(f[i]) != mp.end())
    63                 nx[i] = mp[f[i]];
    64             else
    65                 nx[i] = n + 1;
    66             mp[f[i]] = i;
    67         }
    68         for (int i = 1; i <= n; ++i)
    69         {
    70             if (pre[i] == 0) v[i] = w[f[i]];
    71             else if (v[pre[i]] == w[f[pre[i]]]) v[i] = -w[f[i]]; 
    72             else v[i] = 0;
    73         }
    74         SEG::init();
    75         for (int i = 1; i <= n; ++i)
    76             SEG::update(1, 1, n, i, n, v[i]);
    77         ll res = 0;
    78         for (int i = 1; i <= n; ++i)
    79         {
    80             res = max(res, SEG::Max[1]);
    81             SEG::update(1, 1, n, i, n, -v[i]);
    82             if (nx[i] != n + 1)
    83             {
    84                 SEG::update(1, 1, n, nx[i], n, -v[nx[i]]);
    85                 v[nx[i]] = w[f[nx[i]]];
    86                 SEG::update(1, 1, n, nx[i], n, v[nx[i]]);
    87                 if (nx[nx[i]] != n + 1)
    88                 {
    89                     v[nx[nx[i]]] = -v[nx[i]];
    90                     SEG::update(1, 1, n, nx[nx[i]], n, -v[nx[i]]);
    91                 }
    92             }
    93         }
    94         printf("%lld
    ", res);
    95     }
    96     return 0;
    97 }
    View Code
  • 相关阅读:
    算法提高 道路和航路
    奇偶剪枝
    二分求值
    并查集--路径压缩
    Oracle数据库导入导出DMP文件
    Spring IoC的实现与思考(一)
    sql基础拾遗
    jquery事件函数的使用之focus
    Java动态代理之cglib
    Java se之动态代理
  • 原文地址:https://www.cnblogs.com/Dup4/p/10013999.html
Copyright © 2011-2022 走看看