zoukankan      html  css  js  c++  java
  • 【线段树 dp】8.6集合

    线段树维护dp

    题目大意

    给定初始大小为 $N$ 的正整数集合。定义两个数$x$和$y$建立联系的的代价为 $|x-y|$。我们定义整数集合的代价为:将每个整数都与至少一个另外的整数建立联系之后,所有联系的最小代价之和。如果集合大小小于等于1,则代价为 0。

    要求动态维护这个正整数集合的代价。

    $n le 200000$


    题目分析

    常规的线段树维护dp

    考虑在权值上处理这个问题:对于一个区间$[l,r]$,在$(l,r)$中的数肯定是自身配对了才优。也就是说一个区间可以被概括成四个状态:$00,01,10,11$其中$0$表示这一个端点暂时没有配对,$1$表示这个端点已经内部配对了。

    接下去就是常规的权值线段树处理dp

     1 #include<bits/stdc++.h>
     2 typedef long long ll;
     3 const ll INF = 1ll<<50;
     4 const int maxn = 200035;
     5 const int LIM = 1000000000;
     6 const int maxNode = 8000035;
     7 
     8 struct node
     9 {
    10     int mn,mx,ls,rs,val;
    11     ll f00,f01,f10,f11;
    12 }f[maxNode];
    13 int n,m,rt,tot,a[maxn];
    14 int stk[maxn<<2],top;
    15 
    16 int read()
    17 {
    18     char ch = getchar();
    19     int num = 0, fl = 1;
    20     for (; !isdigit(ch); ch=getchar())
    21         if (ch=='-') fl = -1;
    22     for (; isdigit(ch); ch=getchar())
    23         num = (num<<1)+(num<<3)+ch-48;
    24     return num*fl;
    25 }
    26 void pushup(int rt)
    27 {
    28     int l = f[rt].ls, r = f[rt].rs, gap = f[r].mn-f[l].mx;
    29     if (!l&&!r){
    30         f[rt].f00 = f[rt].f01 = f[rt].f10 = f[rt].f11 = INF;
    31     }else if (!l||!r){ 
    32         f[rt].mn = f[l+r].mn, f[rt].mx = f[l+r].mx;
    33         f[rt].f00 = f[l+r].f00, f[rt].f01 = f[l+r].f01;
    34         f[rt].f10 = f[l+r].f10, f[rt].f11 = f[l+r].f11;
    35     }else{
    36         f[rt].mn = f[l].mn, f[rt].mx = f[r].mx;
    37         f[rt].f00 = std::min(std::min(f[l].f00+f[r].f00+gap, f[l].f00+f[r].f10+gap), std::min(f[l].f01+f[r].f00+gap, f[l].f01+f[r].f10));
    38         f[rt].f01 = std::min(std::min(f[l].f00+f[r].f01+gap, f[l].f00+f[r].f11+gap), std::min(f[l].f01+f[r].f01+gap, f[l].f01+f[r].f11));
    39         f[rt].f10 = std::min(std::min(f[l].f10+f[r].f00+gap, f[l].f10+f[r].f10+gap), std::min(f[l].f11+f[r].f00+gap, f[l].f11+f[r].f10));
    40         f[rt].f11 = std::min(std::min(f[l].f10+f[r].f01+gap, f[l].f10+f[r].f11+gap), std::min(f[l].f11+f[r].f01+gap, f[l].f11+f[r].f11));
    41     }
    42 }
    43 void insert(int &rt, int l, int r, int c, int w)
    44 {
    45     if (!rt){
    46         if (top) rt = stk[top--];
    47         else rt = ++tot;
    48         f[rt].ls = f[rt].rs = f[rt].val = f[rt].f00 = f[rt].f01 = f[rt].f10 = f[rt].f11 = 0;
    49     }
    50     f[rt].val += w;
    51     if (l==r) f[rt].mn = f[rt].mx = c, f[rt].f11 = INF;
    52     else{
    53         int mid = (l+r)>>1;
    54         if (c <= mid)
    55             insert(f[rt].ls, l, mid, c, w);
    56         else insert(f[rt].rs, mid+1, r, c, w);
    57         pushup(rt);
    58     }
    59     if (!f[rt].val) stk[++top] = rt, rt = 0;
    60 }
    61 int main()
    62 {
    63     n = read(), m = read();
    64     for (int i=1; i<=n; i++) insert(rt, 0, LIM, read(), 1);
    65     for (int i=1; i<=m; i++)
    66     {
    67         int opt = read()==1?1:-1;
    68         insert(rt, 0, LIM, read(), opt);
    69         printf("%lld
    ",f[1].f11);
    70     }
    71     return 0;
    72 }

    END

  • 相关阅读:
    VS 2010 制作 Windows Service 安装包
    Postback 之后保持浏览器滚动条的位置
    Stream之list转map及问题解决
    List.sort()排序功能
    The content of element type "resultMap"
    MyBatis 一对一,一对多,多对多
    Java Array、List、Set互相转化
    Java流(Stream)操作实例-筛选、映射、查找匹配
    JAVA系列笔记十八之nohup实现后台运行程序
    VSCode汇总
  • 原文地址:https://www.cnblogs.com/antiquality/p/11494019.html
Copyright © 2011-2022 走看看