CF132E Bits of merry old England
解:略一思索:网络流啊!(别问我是怎么想到的......)
发现跟志愿者招募有点像。于是把图建一下,在下面开一条通道,但是每个点又都要经过,这时我们就无脑上下界一波。
通道向点连边,有费用。每个点向它下一次出现的点连边,费用0。每个点还向通道连边,费用0。
上下界费用流跑一下就出来费用了。然后是输出方案,看哪些边有流量,直接模拟。
1 #include <bits/stdc++.h> 2 3 const int N = 1010, INF = 0x3f3f3f3f; 4 5 struct Edge { 6 int nex, v, c, len; 7 Edge(int Nex = 0, int V = 0, int C = 0, int L = 0) { 8 nex = Nex; 9 v = V; 10 c = C; 11 len = L; 12 } 13 }edge[1000000]; int tp = 1; 14 15 int X[N]; 16 17 struct Node { 18 int p, v; 19 bool f; /// 0 print 1 change 20 Node(int P = 0, int V = 0, bool F = 0) { 21 p = P; 22 v = V; 23 f = F; 24 } 25 inline void out() { 26 if(!f) { 27 printf("print("); putchar('a' + p - 1); printf(")\n"); 28 } 29 else { 30 putchar('a' + p - 1); printf("=%d\n", X[v]); 31 } 32 return; 33 } 34 }stk[N]; int top; 35 36 int xx, Last[N], nex[N], in[N], e[N], tag[N]; 37 int n, m, a[N], val[N], pre[N], vis[N], flow[N], d[N]; 38 std::queue<int> Q; 39 40 inline void Max(int &a, const int &b) { 41 a < b ? a = b : 0; 42 return; 43 } 44 45 inline void add(int x, int y, int z, int w) { 46 // printf("add : %d %d %d %d\n", x, y, z, w); 47 edge[++tp] = Edge(e[x], y, z, w); 48 e[x] = tp; 49 edge[++tp] = Edge(e[y], x, 0, -w); 50 e[y] = tp; 51 return; 52 } 53 54 inline bool SPFA(int s, int t) { 55 static int Time = 0; ++Time; 56 memset(d, 0x3f, sizeof(d)); 57 Q.push(s); 58 vis[s] = Time; 59 flow[s] = INF; 60 d[s] = 0; 61 while(!Q.empty()) { 62 int x = Q.front(); 63 Q.pop(); 64 vis[x] = 0; 65 // printf(" x = %d d[x] = %d \n", x, d[x]); 66 for(int i = e[x]; i; i = edge[i].nex) { 67 int y = edge[i].v; 68 if(d[y] > d[x] + edge[i].len && edge[i].c) { 69 d[y] = d[x] + edge[i].len; 70 // printf(" y = %d d[y] = %d \n", y, d[y]); 71 flow[y] = std::min(flow[x], edge[i].c); 72 pre[y] = i; 73 if(vis[y] != Time) { 74 vis[y] = Time; 75 Q.push(y); 76 } 77 } 78 } 79 } 80 return d[t] < INF; 81 } 82 83 inline void update(int s, int t) { 84 int f = flow[t]; 85 // printf("update : %d ", t); 86 while(t != s) { 87 int i = pre[t]; 88 edge[i].c -= f; 89 edge[i ^ 1].c += f; 90 t = edge[i ^ 1].v; 91 // printf("%d ", t); 92 } 93 // printf("\n"); 94 return; 95 } 96 97 inline int solve(int s, int t, int &cost) { 98 int ans = 0; cost = 0; 99 // printf("solve : %d %d \n", s, t); int i = 0; 100 while(SPFA(s, t)) { 101 // printf("loop : %d flow = %d d = %d \n", ++i, flow[t], d[t]); 102 ans += flow[t]; 103 cost += flow[t] * d[t]; 104 update(s, t); 105 } 106 // printf("ans = %d cost = %d\n", ans, cost); 107 return ans; 108 } 109 110 /* 111 7 2 112 1 2 2 4 2 1 2 113 ------------- 11 4 114 6 3 115 1 2 3 1 2 3 116 ------------- 9 4 117 */ 118 119 int main() { 120 scanf("%d%d", &n, &m); 121 for(int i = 1; i <= n; i++) { 122 scanf("%d", &a[i]); 123 int x = a[i]; 124 while(x) { 125 x -= x & (-x); 126 val[i]++; 127 } 128 X[i] = a[i]; 129 } 130 std::sort(X + 1, X + n + 1); 131 xx = std::unique(X + 1, X + n + 1) - X - 1; 132 // printf("xx = %d \n", xx); 133 for(int i = 1; i <= n; i++) { 134 a[i] = std::lower_bound(X + 1, X + xx + 1, a[i]) - X; 135 // printf("a %d = %d \n", i, a[i]); 136 } 137 for(int i = n; i >= 1; i--) { 138 nex[i] = Last[a[i]]; 139 Last[a[i]] = i; 140 } 141 /// add edge 142 143 int s = n * 3 + 2, t = s + 1, ss = s + 2, tt = s + 3; 144 for(int i = 1; i <= n; i++) { 145 // add(i, i + n, [1, 1], 0); 146 in[i + n]++; in[i]--; 147 add(i + 2 * n, i, 1, val[i]); 148 add(i + n, i + 1 + 2 * n, 1, 0); 149 add(i + 2 * n, i + 1 + 2 * n, INF, 0); 150 if(nex[i]) { 151 add(i + n, nex[i], 1, 0); 152 // printf("nex %d = %d add(%d %d)\n", i, nex[i], i + n, nex[i]); 153 } 154 } 155 add(s, 1 + 2 * n, m, 0); 156 add(n + 1 + 2 * n, t, m, 0); 157 int Ck = tp; 158 add(t, s, INF, 0); 159 for(int i = 1; i <= t; i++) { 160 if(in[i]) { 161 if(in[i] > 0) { 162 add(ss, i, in[i], 0); 163 } 164 else { 165 add(i, tt, -in[i], 0); 166 } 167 } 168 } 169 170 int cost1 = 0, cost2 = 0; 171 solve(ss, tt, cost1); 172 for(int i = Ck + 1; i <= tp; i++) { 173 edge[i].c = 0; 174 } 175 solve(s, t, cost2); 176 177 // get ways 178 for(int i = 1; i <= m; i++) { 179 Q.push(i); 180 } 181 for(int j = 1; j <= n; j++) { 182 int x = j + 2 * n; 183 for(int i = e[x]; i; i = edge[i].nex) { 184 int y = edge[i].v; 185 if(y == j && edge[i ^ 1].c) { 186 /// a num -> a[j] 187 tag[j] = Q.front(); 188 Q.pop(); 189 stk[++top] = Node(tag[j], a[j], 1); 190 break; 191 } 192 } 193 // printf("tag[j] = %d \n", tag[j]); 194 stk[++top] = Node(tag[j], 0, 0); 195 x = j + n; 196 for(int i = e[x]; i; i = edge[i].nex) { 197 int y = edge[i].v; 198 if(y == nex[j] && edge[i ^ 1].c) { 199 tag[nex[j]] = tag[j]; 200 break; 201 } 202 if(y == j + 1 + 2 * n && edge[i ^ 1].c) { 203 /// return queue 204 Q.push(tag[j]); 205 break; 206 } 207 } 208 } 209 210 printf("%d %d\n", top, cost1 + cost2); 211 for(int i = 1; i <= top; i++) stk[i].out(); 212 return 0; 213 }