【线段树 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\n",f[1].f11);
70     }
71     return 0;
72 }

 

 

 

 

END

posted @ 2019-09-09 20:25  AntiQuality  阅读(173)  评论(0编辑  收藏  举报