Your search for Heidi is over – you finally found her at a library, dressed up as a human. In fact, she has spent so much time there that she now runs the place! Her job is to buy books and keep them at the library so that people can borrow and read them. There are ndifferent books, numbered 1 through n.
We will look at the library's operation during n consecutive days. Heidi knows in advance that on the i-th day (1 ≤ i ≤ n) precisely one person will come to the library, request to borrow the book ai, read it in a few hours, and return the book later on the same day.
Heidi desperately wants to please all her guests, so she will make sure to always have the book ai available in the library on the i-th day. During the night before the i-th day, she has the option of going to the bookstore (which operates at nights to avoid competition with the library) and buying any book for the price of 1 CHF. Of course, if she already has a book at the library, she does not need to buy it again. Initially, the library contains no books.
There is a problem, though. The capacity of the library is k – this means that at any time, there can be at most k books at the library. If buying a new book would cause Heidi to have more than k books, she must first get rid of some book that she already has, in order to make room for the new book. If she later needs a book that she got rid of, she will need to buy that book again.
You are given k and the sequence of requests for books a1, a2, ..., an. What is the minimum cost (in CHF) of buying new books to satisfy all the requests?
The first line of input will contain two integers n and k (1 ≤ n, k ≤ 80). The second line will contain n integers a1, a2, ..., an (1 ≤ ai ≤ n) – the sequence of book requests.
On a single line print the minimum cost of buying books at the store so as to satisfy all requests.
4 80
1 2 2 1
2
4 1
1 2 2 1
3
4 2
1 2 3 1
3
In the first test case, Heidi is able to keep all books forever. Therefore, she only needs to buy the book 1 before the first day and the book 2 before the second day.
In the second test case, she can only keep one book at a time. Therefore she will need to buy new books on the first, second and fourth day.
In the third test case, before buying book 3 on the third day, she must decide which of the books 1 and 2 she should get rid of. Of course, she should keep the book 1, which will be requested on the fourth day.
题目大意:有一家图书馆,有k个位置放书,有n天每天一个客人来看书,你必须保证客人来看书的时候图书馆里有他要的书,如果图书管理本来有他要的书就不用买,否则要花1元买这本书。图书馆里同时储存的书不能超过k本,求满足所有客人的最小花费
Eazy:n,k<=80
事实上你想不到正解,这个Eazy也很难做
一眼看不出做法,不妨先去看看Medium的数据范围
Medium:其他条件不变,n,k<=400,000
哦,nlogn之类的
但是也不太知道怎么做,想了一下,遇到新书,格子没满肯定是直接买新的,格子满了的话,不妨丢掉下一次出现最晚的一本,自己想不出反例,写了一发交上去A了
具体实现用个vector维护出现位置,平衡树维护一下最大值就好了
我的treap写的真难看
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <algorithm> 5 #include <string> 6 #include <cstring> 7 #include <cmath> 8 #include <map> 9 #include <stack> 10 #include <set> 11 #include <vector> 12 #include <queue> 13 #include <time.h> 14 #define eps 1e-7 15 #define INF 0x3f3f3f3f 16 #define MOD 1000000007 17 #define rep0(j,n) for(int j=0;j<n;++j) 18 #define rep1(j,n) for(int j=1;j<=n;++j) 19 #define pb push_back 20 #define set0(n) memset(n,0,sizeof(n)) 21 #define ll long long 22 #define ull unsigned long long 23 #define iter(i,v) for(edge *i=head[v];i;i=i->nxt) 24 #define max(a,b) (a>b?a:b) 25 #define min(a,b) (a<b?a:b) 26 #define print_runtime printf("Running time:%.3lfs ",double(clock())/1000.0) 27 #define TO(j) printf(#j": %d ",j); 28 //#define OJ 29 using namespace std; 30 const int MAXINT = 400010; 31 const int MAXNODE = 100010; 32 const int MAXEDGE = 2 * MAXNODE; 33 char BUF, *buf; 34 int read() { 35 char c = getchar(); int f = 1, x = 0; 36 while (!isdigit(c)) { if (c == '-') f = -1; c = getchar(); } 37 while (isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } 38 return f*x; 39 } 40 char get_ch() { 41 char c = getchar(); 42 while (!isalpha(c)) c = getchar(); 43 return c; 44 } 45 //------------------- Head Files ----------------------// 46 struct info { 47 int v, p; 48 info() {} 49 info(int _v, int _p) :v(_v), p(_p) {} 50 }; 51 info add(info a, info b) { 52 return a.p>b.p ? a : b; 53 } 54 struct node { 55 int key; 56 info mx, p; 57 node *fa, *c[2]; 58 int checkfa() { 59 if (this == fa->c[0]) return 0; 60 else return 1; 61 } 62 void pushup() { 63 mx = add(add(p, c[0]->mx), c[1]->mx); 64 } 65 }; 66 struct treap { 67 node mp[MAXINT * 2], nil; 68 node *root, *NIL; 69 int cnt; 70 treap() { 71 NIL = &nil; 72 NIL->fa = NIL->c[0] = NIL->c[1] = NIL; 73 NIL->mx = NIL->p = info(-1, -1); 74 NIL->key = -1; 75 root = NIL; 76 } 77 node *newnode(info v, node *fa) { 78 node *p = &mp[cnt++]; 79 p->mx = p->p = v; 80 p->fa = fa; 81 p->c[0] = p->c[1] = NIL; 82 p->key = rand(); 83 return p; 84 } 85 void rotate(node *p, int d) { 86 node *pfa = p->fa; 87 p->fa = pfa->fa; 88 p->fa->c[pfa->checkfa()] = p; 89 pfa->fa = p; 90 pfa->c[d ^ 1] = p->c[d]; 91 pfa->c[d ^ 1]->fa = pfa; 92 p->c[d] = pfa; 93 if (root == pfa) root = p; 94 pfa->pushup(); 95 } 96 void insert(info v) { 97 node *p = root,*pfa; 98 if (p == NIL) { root = newnode(v, NIL); return; } 99 while (p!=NIL) { 100 pfa = p; 101 if (p->p.v>v.v) p = p->c[0]; 102 else p = p->c[1]; 103 } 104 if (pfa->p.v>v.v) pfa->c[0] = newnode(v, pfa), p = pfa->c[0]; 105 else pfa->c[1] = newnode(v, pfa), p = pfa->c[1]; 106 while (p->key<p->fa->key) rotate(p, p->checkfa() ^ 1); 107 while (p != NIL) { 108 p->pushup(); 109 p = p->fa; 110 } 111 } 112 void del(int v) { 113 node *p = root; 114 while (p->p.v != v) { 115 if (p->p.v>v) p = p->c[0]; 116 if (p->p.v<v) p = p->c[1]; 117 } 118 if (p == root) { 119 if (p->c[0] == NIL) root = p->c[1]; 120 else if (p->c[1] == NIL) root = p->c[0]; 121 else if (p->c[0]->key>p->c[1]->key) { 122 root = p->c[1]; 123 } 124 else { 125 root = p->c[0]; 126 } 127 } 128 while (p->c[0] != NIL&&p->c[1] != NIL) { 129 if (p->c[0]->key>p->c[1]->key) { 130 rotate(p->c[1], 0); 131 } 132 else { 133 rotate(p->c[0], 1); 134 } 135 } 136 if (p->c[0] == NIL&&p->c[1] == NIL) { 137 p->fa->c[p->checkfa()] = NIL; 138 } 139 else if (p->c[0] == NIL) { 140 p->fa->c[p->checkfa()] = p->c[1]; 141 p->c[1]->fa = p->fa; 142 } 143 else { 144 p->fa->c[p->checkfa()] = p->c[0]; 145 p->c[0]->fa = p->fa; 146 } 147 148 while (p != NIL) { 149 p->pushup(); 150 p = p->fa; 151 } 152 } 153 info getmx() { 154 return root->mx; 155 } 156 }tp; 157 int a[MAXINT], n, k; 158 int v[MAXINT], c[MAXINT]; 159 vector<int> pos[MAXINT]; 160 void get_input(); 161 void work(); 162 int main() { 163 srand(559320414); 164 get_input(); 165 work(); 166 return 0; 167 } 168 void work() { 169 int num = 0, sum = 0; 170 for (int i = 0; i<n; i++) { 171 c[a[i]]++; 172 if (v[a[i]]) { 173 tp.del(a[i]); 174 tp.insert(info(a[i], pos[a[i]][c[a[i]]])); 175 continue; 176 } 177 sum++; 178 if (num<k) { 179 num++; 180 tp.insert(info(a[i], pos[a[i]][c[a[i]]])); 181 v[a[i]] = 1; 182 } 183 else { 184 info ans = tp.getmx(); 185 v[ans.v] = 0; 186 tp.del(ans.v); 187 tp.insert(info(a[i], pos[a[i]][c[a[i]]])); 188 v[a[i]] = 1; 189 } 190 } 191 printf("%d ", sum); 192 } 193 void get_input() { 194 n = read(); k = read(); 195 rep0(i, n) a[i] = read(), pos[a[i]].push_back(i); 196 rep1(i, n) pos[i].push_back(n + i); 197 }
Hard:书有不同的费用,n,k<=80
这个数据范围,费用流吧
各种东西网上套也没想出来怎么建模
看了题解,给这个思路跪了
每一天i拆成两个点2i,2i+1
SS---(1,第i天所需要的书的费用)-->2i--(1,M(非常小的负数))--->2i+1---(1,0)--->TT
然后对于每个2i+1,向它后面的每一天的2j连边,边权为(1,0)如果a[i]==a[j],(1,c[a[j]]) otherwise
进行k次负增广(如果增广使答案更大就拒绝接受),最终的费用+n*M就是答案
这个图看上去让人莫名其妙,但似乎感觉很厉害
他为什么对呢?
显然所有(1,M)的边都会被经过,相当于满足了所有客人的需求
那么我们增广k次,在图里剩下的就是k条路径
我们单独考虑每个书架,如果把一个客人分配给一个书架,这个书架的书可以有两个来源:
1、之前从来没有过书,新了买一本
2、从以前继承一本,可能不好用,丢掉新买了一本,也可能直接就能用
是不是有点清楚了
1就是 SS---(1,第i天所需要的书的费用)-->2i的边
2就是 2i+1,向它后面的每一天的2j连边,边权为(1,0)如果a[i]==a[j],(1,c[a[j]]) otherwise 的边
网络中的每一条路径都是一个书架里的书变化的过程
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <algorithm> 5 #include <string> 6 #include <cstring> 7 #include <cmath> 8 #include <map> 9 #include <stack> 10 #include <set> 11 #include <vector> 12 #include <queue> 13 #include <time.h> 14 #define eps 1e-7 15 #define INF 0x3f3f3f3f 16 #define MOD 1000000007 17 #define rep0(j,n) for(int j=0;j<n;++j) 18 #define rep1(j,n) for(int j=1;j<=n;++j) 19 #define pb push_back 20 #define set0(n) memset(n,0,sizeof(n)) 21 #define ll long long 22 #define ull unsigned long long 23 #define iter(i,v) for(edge *i=head[v];i;i=i->nxt) 24 #define max(a,b) (a>b?a:b) 25 #define min(a,b) (a<b?a:b) 26 #define print_runtime printf("Running time:%.3lfs ",double(clock())/1000.0) 27 #define TO(j) printf(#j": %d ",j); 28 //#define OJ 29 using namespace std; 30 const int MAXINT = 85; 31 const int MAXNODE = 200; 32 const int MAXEDGE = 20000; 33 char BUF, *buf; 34 int read() { 35 char c = getchar(); int f = 1, x = 0; 36 while (!isdigit(c)) { if (c == '-') f = -1; c = getchar(); } 37 while (isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } 38 return f * x; 39 } 40 char get_ch() { 41 char c = getchar(); 42 while (!isalpha(c)) c = getchar(); 43 return c; 44 } 45 //------------------- Head Files ----------------------// 46 int cnt, q[MAXNODE * MAXNODE], inq[MAXNODE], SS = MAXNODE - 2, TT = MAXNODE - 1, n, a[MAXINT], c[MAXINT], k; 47 ll dis[MAXNODE]; 48 struct edge { 49 int u, v, c, cost; 50 edge *nxt; 51 edge(int _u, int _v, int _c, int _cost, edge *_nxt) : u(_u), v(_v), c(_c), cost(_cost), nxt(_nxt) {} 52 edge() {} 53 } mp[MAXEDGE], *head[MAXNODE], *from[MAXNODE]; 54 void addedge(int u, int v, int c, int cost) { 55 mp[cnt] = edge(u, v, c, cost, head[u]); 56 head[u] = &mp[cnt++]; 57 mp[cnt] = edge(v, u, 0, -cost, head[v]); 58 head[v] = &mp[cnt++]; 59 } 60 edge* rev(edge *e) { 61 return &mp[(e - mp) ^ 1]; 62 } 63 int spfa(int ss, int tt) { 64 memset(dis, INF, sizeof(dis)); 65 int *h, *t; 66 h = t = q; 67 dis[*t++ = ss] = 0; 68 while (h != t) { 69 int p = *h++; 70 inq[p] = 0; 71 iter(i, p) { 72 if (i->c && dis[i->v] > dis[p] + i->cost) { 73 dis[i->v] = dis[p] + i->cost; 74 from[i->v] = i; 75 if (!inq[i->v]) { 76 *t++ = i->v; 77 inq[i->v] = 1; 78 } 79 } 80 } 81 } 82 return dis[tt] != 0x3f3f3f3f3f3f3f3f; 83 } 84 ll extend(int ss, int tt) { 85 int p = tt, f = INF; 86 ll cost = 0; 87 while (p != ss) { 88 f = min(f, from[p]->c); 89 cost += from[p]->cost; 90 p = from[p]->u; 91 } 92 p = tt; 93 while (p != ss) { 94 from[p]->c -= f; 95 rev(from[p])->c += f; 96 p = from[p]->u; 97 } 98 return cost*f; 99 } 100 ll minflow(int ss, int tt) { 101 ll ans = 0x3f3f3f3fll * n; 102 rep0(i, k) { 103 if (!spfa(ss, tt)) break; 104 if (dis[TT] >= 0) break; 105 ans += extend(ss, tt); 106 } 107 return ans; 108 } 109 void get_input(); 110 void work(); 111 int main() { 112 get_input(); 113 work(); 114 return 0; 115 } 116 void work() { 117 rep0(i, n) { 118 addedge(SS, i * 2, 1, c[a[i]]); 119 addedge(i * 2 + 1, TT, 1, 0); 120 addedge(i * 2, i * 2 + 1, 1, -INF); 121 } 122 rep0(i, n) { 123 for (int j = i + 1; j<n; j++) { 124 if (a[i] == a[j]) addedge(i * 2 + 1, j * 2, 1, 0); 125 else addedge(i * 2 + 1, j * 2, 1, c[a[j]]); 126 } 127 } 128 printf("%lld ", minflow(SS, TT)); 129 } 130 void get_input() { 131 n = read(); k = read(); 132 rep0(i, n) a[i] = read(); 133 rep1(i, n) c[i] = read(); 134 }