2016 Multi-University Training Contest 2
1001 Acperience
1002 Born Slippy
考虑链上版本,有dp[i] = max{dp[j] + opt(w[i], w[j])}
由于w的范围是2^16,拆成前8位后8位。
引入辅助ds[x][y]表示dp[j]前8位是x,dp[i]后8位是y时的max{dp[j] + opt(dp[j]后8位, dp[i]后8位)}
这样的好处是,更新dp[i]时,由于dp[i]的后8位和前8位都是已知的,只要用2^8枚举dp[j]的前8位,假设为k
得到dp[i] = max{ds[k][y] + (opt(k, dp[i]前8位) << 8)}
然后再更新ds数组,枚举后继的dp值后8位,假设为k,ds[dp[i]前8位][k] = max{dp[i] + opt(dp[i]后8位, k)}
再考虑树上版本,因为每次改ds只会改255个值,在更新ds前先备份一下,回溯的时候还原即可。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 typedef long long LL; 7 const LL mod = 1e9 + 7; 8 const int maxn = 66666; 9 LL w[maxn], dp[maxn], ds[256][256], cpy[maxn][256]; 10 char opt[11]; 11 12 // edge 13 int cnt, h[maxn]; 14 void init() 15 { 16 cnt = 0; 17 memset(h, 0, sizeof(h)); 18 } 19 struct edge 20 { 21 int to, pre; 22 } e[maxn]; 23 void add(int from, int to) 24 { 25 cnt++; 26 e[cnt].pre = h[from]; 27 e[cnt].to = to; 28 h[from] = cnt; 29 } 30 31 // dp 32 LL F(LL A, LL B) 33 { 34 if(opt[0] == 'A') return A & B; 35 if(opt[0] == 'X') return A ^ B; 36 return A | B; 37 } 38 void dfs(int x) 39 { 40 dp[x] = 0; 41 LL A = w[x] >> 8, B = w[x] & 255; 42 for(int i = 0; i <= 255; i++) 43 if(ds[i][B] != -1) dp[x] = max(dp[x], ds[i][B] + (F(i, A) << 8)); 44 45 for(int i = 0; i <= 255; i++) 46 { 47 cpy[x][i] = ds[A][i]; 48 ds[A][i] = max(ds[A][i], dp[x] + F(i, B)); 49 } 50 for(int i = h[x]; i; i = e[i].pre) dfs(e[i].to); 51 for(int i = 0; i <= 255; i++) ds[A][i] = cpy[x][i]; 52 } 53 54 int main(void) 55 { 56 memset(ds, -1, sizeof(ds)); 57 int T; 58 scanf("%d", &T); 59 while(T--) 60 { 61 init(); 62 int n; 63 scanf("%d %s", &n, opt); 64 for(int i = 1; i <= n; i++) scanf("%d", w + i); 65 for(int i = 2; i <= n; i++) 66 { 67 int f; 68 scanf("%d", &f); 69 add(f, i); 70 } 71 72 dfs(1); 73 LL ans = 0; 74 for(int i = 1; i <= n; i++) ans = (ans + i * (dp[i] + w[i])) % mod; 75 printf("%I64d\n", ans); 76 77 } 78 return 0; 79 }
1004 Differencia
在每个线段树节点[l, r]维护排好序的b[l]-b[r]。
每次修改,在每个区间内二分小于等于x的数有几个,就得到一个nlognlogn的做法。
再维护对于[l, r]内第i大的数,在左子树中,有多少数字小于等于它,存在L[p][i]里,右子树同理。
然后每次修改,在根节点二分,找有多少个数小于等于x,
然后下传到左右子树的时候,x是多少已经不重要了,只要知道第一个小于等于x的数在什么位置,
只要考虑左子树有多少数小于等于L[p][i],右子树有多少数小于等于R[p][i]。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 typedef long long LL; 6 const int mod = 1e9 + 7; 7 const int maxn = 1e5 + 10; 8 const int C = ~(1<<31), M = (1<<16)-1; 9 int a[maxn], b[maxn], A, B; 10 int all[maxn], t1[maxn], t2[maxn]; 11 12 struct node 13 { 14 int id, x; 15 node() {} 16 node(int ID, int X): id(ID), x(X) {} 17 friend bool operator < (node A, node B) 18 { 19 return A.x < B.x; 20 } 21 } t[maxn]; 22 23 // segment_tree 24 int sum[maxn<<2], tag[maxn<<2]; 25 int *L[maxn<<2], *R[maxn<<2]; 26 27 void gather(int p) 28 { 29 sum[p] = sum[p<<1] + sum[p<<1|1]; 30 } 31 32 void push(int p) 33 { 34 if(tag[p] != -1) 35 { 36 int rk = tag[p]; 37 sum[p<<1] = tag[p<<1] = L[p][rk]; 38 sum[p<<1|1] = tag[p<<1|1] = R[p][rk]; 39 tag[p] = -1; 40 } 41 } 42 43 void init(int p, int l, int r) 44 { 45 int mid = (l + r) >> 1; 46 L[p] = new int[r - l + 10]; 47 R[p] = new int[r - l + 10]; 48 if(l != r) init(p<<1, l, mid), init(p<<1|1, mid + 1, r); 49 } 50 51 void build(int p, int l, int r) 52 { 53 tag[p] = -1; 54 L[p][0] = R[p][0] = 0; 55 56 if(l < r) 57 { 58 int mid = (l + r) >> 1; 59 60 int ct = 0, ct1 = 0, ct2 = 0; 61 t[ct++].x = 0, t1[ct1++] = 0, t2[ct2++] = 0; 62 for(int i = l; i <= mid; i++) t[ct].x = b[i], t[ct++].id = 0; 63 for(int i = mid + 1; i <= r; i++) t[ct].x = b[i], t[ct++].id = 1; 64 65 sort(t, t + ct); 66 for(int i = 1; i < ct; i++) 67 { 68 if(!t[i].id) t1[ct1++] = t[i].x; 69 else t2[ct2++] = t[i].x; 70 } 71 72 int p1 = ct1 = 0, p2 = ct2 = 0; 73 for(int i = 1; i <= r - l + 1; i++) 74 { 75 while(p1 <= mid - l && t1[p1+1] <= t[i].x) p1++; 76 while(p2 < r - mid && t2[p2+1] <= t[i].x) p2++; 77 L[p][++ct1] = p1, R[p][++ct2] = p2; 78 } 79 80 build(p<<1, l, mid); 81 build(p<<1|1, mid + 1, r); 82 gather(p); 83 } 84 else 85 { 86 L[p][1] = R[p][1] = 1; 87 sum[p] = a[l] >= b[l]; 88 } 89 } 90 91 void modify(int p, int tl, int tr, int l, int r, int rk) 92 { 93 if(tr < l || r < tl) return; 94 if(l <= tl && tr <= r) 95 { 96 sum[p] = tag[p] = rk; 97 return; 98 } 99 push(p); 100 int mid = (tl + tr) >> 1; 101 modify(p<<1, tl, mid, l, r, L[p][rk]); 102 modify(p<<1|1, mid+1, tr, l, r, R[p][rk]); 103 gather(p); 104 } 105 106 int query(int p, int tl, int tr, int l, int r) 107 { 108 if(tr < l || r < tl) return 0; 109 if(l <= tl && tr <= r) return sum[p]; 110 push(p); 111 int mid = (tl + tr) >> 1; 112 int ret = query(p<<1, tl, mid, l, r); 113 ret += query(p<<1|1, mid+1, tr, l, r); 114 return ret; 115 } 116 117 118 int rnd(int last) 119 { 120 A = (36969 + (last >> 3)) * (A & M) + (A >> 16); 121 B = (18000 + (last >> 3)) * (B & M) + (B >> 16); 122 return (C & ((A << 16) + B)) % 1000000000; 123 } 124 125 126 int main(void) 127 { 128 init(1, 1, maxn); 129 int T; 130 scanf("%d", &T); 131 while(T--) 132 { 133 134 int n, m; 135 scanf("%d %d %d %d", &n, &m, &A, &B); 136 for(int i = 1; i <= n; i++) scanf("%d", a + i); 137 for(int i = 1; i <= n; i++) scanf("%d", b + i); 138 139 all[0] = 0; 140 for(int i = 1; i <= n; i++) all[i] = b[i]; 141 sort(all, all + n + 1); 142 143 build(1, 1, n); 144 145 int ans = 0; 146 int last = 0; 147 for(int i = 1; i <= m; i++) 148 { 149 int l = rnd(last) % n + 1, r = rnd(last) % n + 1, x = rnd(last) + 1; 150 if(l > r) swap(l, r); 151 if((l + r + x) % 2) 152 { 153 int rk = x >= all[n] ? n : lower_bound(all, all + n + 1, x + 1) - all - 1; 154 modify(1, 1, n, l, r, rk); 155 } 156 else 157 { 158 last = query(1, 1, n, l, r); 159 ans = (ans + (LL) i * (LL) last) % mod; 160 } 161 } 162 163 printf("%d\n", ans); 164 165 } 166 return 0; 167 }
1005 Eureka
先按x排序,然后扫一遍所有点,后面点极角排序,数贡献。
感觉自己的计数好像弄复杂了……
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; typedef long long LL; const LL mod = 1e9 + 7; LL Pow[1111]; int gcd(int a, int b) { return a % b ? gcd(b, a % b) : b; } struct point { int x, y; } p[1111], tmp[1111]; bool cmp1(point A, point B) { if(A.x != B.x) return A.x < B.x; return A.y < B.y; } bool cmp2(point A, point B) { return 1.0 * A.y * B.x < 1.0 * B.y * A.x; } int main(void) { Pow[0] = 1; for(int i = 1; i <= 1000; i++) Pow[i] = Pow[i-1] * 2 % mod; int T; scanf("%d", &T); while(T--) { int n; scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d %d", &p[i].x, &p[i].y); sort(p + 1, p + 1 + n, cmp1); LL ans = 0; for(int i = 1; i <= n; i++) { int cnt1 = 1, cnt2 = 0; for(int j = i + 1; j <= n; j++) { if(p[j].x == p[i].x && p[j].y == p[i].y) cnt1++; else { tmp[cnt2].x = p[j].x - p[i].x; tmp[cnt2].y = p[j].y - p[i].y; if(!tmp[cnt2].x) tmp[cnt2].y /= abs(tmp[cnt2].y); else if(!tmp[cnt2].y) tmp[cnt2].x /= abs(tmp[cnt2].x); else { int g = gcd(abs(tmp[cnt2].x), abs(tmp[cnt2].y)); tmp[cnt2].x /= g, tmp[cnt2].y /= g; } cnt2++; } } sort(tmp, tmp + cnt2, cmp2); int pos = 0, cnt = 1; LL all = (Pow[cnt1] - cnt1 - 1 + mod) % mod; while(pos < cnt2) { while(pos < cnt2 - 1 && tmp[pos].x == tmp[pos+1].x && tmp[pos].y == tmp[pos+1].y) pos++, cnt++; ans = (ans + Pow[cnt1+cnt] - Pow[cnt] - cnt1 - all + mod + mod) % mod; pos++, cnt = 1; } ans = (ans + all) % mod; i += cnt1 - 1; } printf("%I64d\n", ans); } return 0; }
1006 Fantasia
看了这里的图才懂。
这个方法可以把所有的非孤立点和新加的点搞成一棵树。
dp一下能算出每个子树的子树乘积和孩子和。再统计一下。孤立点要另外算。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 #include <stack> 6 #include <algorithm> 7 using namespace std; 8 typedef pair<int, int> pii; 9 typedef long long LL; 10 const LL mod = 1e9 + 7; 11 const int maxn = 1e5 + 10; 12 LL sum[maxn<<1], pro[maxn<<1]; 13 14 bool single[maxn], vis[maxn<<1]; 15 int w[maxn]; 16 int n; 17 vector<int> rt; 18 19 20 // edge 21 int cnt[2], h[2][maxn<<1]; 22 void init() 23 { 24 cnt[0] = cnt[1] = 0; 25 memset(h, -1, sizeof(h)); 26 } 27 struct edge 28 { 29 int to, pre; 30 bool used; 31 } e[2][maxn<<2]; 32 void add(int i, int from, int to) 33 { 34 e[i][cnt[i]].pre = h[i][from]; 35 e[i][cnt[i]].to = to; 36 e[i][cnt[i]].used = 0; 37 h[i][from] = cnt[i]++; 38 } 39 40 41 // BCC 42 int pre[maxn], bccno[maxn], dfs_clock, bcc_cnt; 43 stack<pii> S; 44 int dfs(int u, int fa) 45 { 46 int lowu = pre[u] = ++dfs_clock; 47 if(h[0][u] == -1) {single[u] = 1; return lowu;} 48 for(int i = h[0][u]; i != -1; i = e[0][i].pre) 49 { 50 // multi-edge 51 if(e[0][i].used) continue; 52 e[0][i].used = e[0][i^1].used = 1; 53 54 int v = e[0][i].to; 55 pii E = pii(u, v); 56 if(!pre[v]) 57 { 58 S.push(E); 59 int lowv = dfs(v, u); 60 lowu = min(lowu, lowv); 61 if(lowv >= pre[u]) 62 { 63 bcc_cnt++; 64 while(1) 65 { 66 pii x = S.top(); S.pop(); 67 if(bccno[x.first] != bcc_cnt) 68 { 69 bccno[x.first] = bcc_cnt; 70 add(1, x.first, n + bcc_cnt); 71 add(1, n + bcc_cnt, x.first); 72 } 73 if(bccno[x.second] != bcc_cnt) 74 { 75 bccno[x.second] = bcc_cnt; 76 add(1, x.second, n + bcc_cnt); 77 add(1, n + bcc_cnt, x.second); 78 } 79 if(x.first == u && x.second == v) break; 80 } 81 } 82 } 83 else if(pre[v] < pre[u] && v != fa) 84 { 85 S.push(E); 86 lowu = min(lowu, pre[v]); 87 } 88 } 89 return lowu; 90 } 91 92 void find_bcc() 93 { 94 memset(pre, 0, sizeof(pre)); 95 memset(bccno, 0, sizeof(bccno)); 96 memset(single, 0, sizeof(single)); 97 dfs_clock = bcc_cnt = 0; 98 for(int i = 1; i <= n; i++) 99 if(!pre[i]) dfs(i, -1); 100 } 101 102 103 // tree_dp 104 int id[maxn<<1]; 105 void dfs2(int x, int ID) 106 { 107 id[x] = ID, vis[x] = 1; 108 sum[x] = 0, pro[x] = x > n ? 1 : w[x]; 109 for(int i = h[1][x]; i != -1; i = e[1][i].pre) 110 { 111 int to = e[1][i].to; 112 if(vis[to]) continue; 113 dfs2(to, ID); 114 sum[x] = (sum[x] + pro[to]) % mod; 115 pro[x] = (pro[x] * pro[to]) % mod; 116 } 117 } 118 119 120 // inv 121 LL qpow(LL a, LL b) 122 { 123 LL ret = 1LL; 124 while(b) 125 { 126 if(b & 1) ret = ret * a % mod; 127 a = a * a % mod; 128 b >>= 1; 129 } 130 return ret; 131 } 132 LL inv(LL x) 133 { 134 return qpow(x, mod - 2); 135 } 136 137 138 int main(void) 139 { 140 141 int T; 142 scanf("%d", &T); 143 while(T--) 144 { 145 int m; 146 scanf("%d %d", &n, &m); 147 for(int i = 1; i <= n; i++) scanf("%d", w + i); 148 init(); 149 for(int i = 1; i <= m; i++) 150 { 151 int u, v; 152 scanf("%d %d", &u, &v); 153 add(0, u, v), add(0, v, u); 154 } 155 find_bcc(); 156 157 rt.clear(); 158 memset(vis, 0, sizeof(vis)); 159 for(int i = 1; i <= bcc_cnt; i++) 160 { 161 if(vis[n+i]) continue; 162 rt.push_back(i + n); 163 dfs2(i + n, i + n); 164 } 165 166 LL tot = 0; 167 for(int i = 1; i <= n; i++) if(single[i]) tot = (tot + w[i]) % mod; 168 int sz = rt.size(); 169 for(int i = 0; i < sz; i++) tot = (tot + pro[rt[i]]) % mod; 170 171 LL ans = 0; 172 for(int i = 1; i <= n; i++) 173 { 174 if(single[i]) ans = (ans + (LL) i * (tot - w[i] + mod) % mod) % mod; 175 else ans = (ans + LL(i) * (tot - pro[id[i]] + mod + pro[id[i]] * inv(pro[i]) % mod + sum[i]) % mod) % mod; 176 } 177 178 printf("%I64d\n", ans); 179 180 } 181 return 0; 182 }
1007 Glorious Brilliance
先预处理一下最短路和路径。
然后给每个联通块染色,如果可行的话跑最小费用流。
要注意的是左右点数相等的时候,涂色方案有两种,都要考虑,取代价小的。
输出路径的时候,每次找到第一个两端颜色不同的边开始换位置。
不会写函数还讨论了颜色导致代码非常丑。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 #include <queue> 6 #include <algorithm> 7 using namespace std; 8 typedef pair<int, int> pii; 9 vector<pii> tmp, v1, v2, path; 10 int n; 11 12 // Floyd 13 int G[555][555], mid[555][555]; 14 void Floyd() 15 { 16 memset(mid, 0, sizeof(mid)); 17 for(int k = 1; k <= n; k++) 18 { 19 for(int i = 1; i <= n; i++) 20 { 21 for(int j = 1; j <= n; j++) 22 { 23 if(G[i][j] > G[i][k] + G[k][j]) 24 { 25 mid[i][j] = k; 26 G[i][j] = G[i][k] + G[k][j]; 27 } 28 } 29 } 30 } 31 } 32 33 void get_path(int i, int j) 34 { 35 if(mid[i][j]) get_path(i, mid[i][j]), get_path(mid[i][j], j); 36 else path.push_back(pii(i, j)); 37 } 38 39 // BG_draw 40 int c0, c1, n0, n1; 41 int cl[555]; 42 int nc[555], used[555], id[555]; 43 bool draw(int x, int c, int no) 44 { 45 used[x] = 1, nc[x] = c, id[x] = no; 46 if(cl[x]) c1++; else c0++; 47 if(c) n1++; else n0++; 48 for(int i = 1; i <= n; i++) 49 { 50 if(G[x][i] != 1 || used[i]) continue; 51 if(!draw(i, c^1, no)) return false; 52 } 53 return true; 54 } 55 56 void flip(int x) 57 { 58 swap(n0, n1); 59 for(int i = 1; i <= n; i++) if(id[i] == x) nc[i] ^= 1; 60 } 61 62 63 //SPFA_min_cost_flow 64 const int INF = 1e9; 65 const int maxn = 1e6; 66 int dist[555], vis[555]; 67 int pv[555], pe[555]; 68 int cnt, h[555]; 69 70 struct edge 71 { 72 int to, pre, cap, cost; 73 } e[maxn<<1]; 74 75 void init()//Don't forget 76 { 77 cnt = 0; 78 memset(h, -1, sizeof(h)); 79 } 80 81 void add(int from, int to, int cap, int cost) 82 { 83 e[cnt].pre = h[from]; 84 e[cnt].to = to; 85 e[cnt].cap = cap; 86 e[cnt].cost = cost; 87 h[from] = cnt; 88 cnt++; 89 } 90 91 void ad(int from, int to, int cap, int cost) 92 { 93 add(from, to, cap, cost); 94 add(to, from, 0, -cost); 95 } 96 97 int min_cost_flow(int s, int t, int f) 98 { 99 int ret = 0; 100 while(f > 0) 101 { 102 memset(vis, 0, sizeof(vis)); 103 for(int i = 0; i < 555; i++) dist[i] = INF; 104 dist[s] = 0; 105 queue<int> q; 106 q.push(s); 107 while(!q.empty()) 108 { 109 int v = q.front(); q.pop(); 110 vis[v] = 0; 111 for(int i = h[v]; i >= 0; i = e[i].pre) 112 { 113 int to = e[i].to, cap = e[i].cap, cost = e[i].cost; 114 if(cap > 0 && dist[to] > dist[v] + cost) 115 { 116 pv[to] = v, pe[to] = i; 117 dist[to] = dist[v] + cost; 118 if(!vis[to]) q.push(to); 119 vis[to] = 1; 120 } 121 } 122 } 123 124 if(dist[t] == INF) return -1;//modify here 125 126 int d = f; 127 for(int v = t; v != s; v = pv[v]) 128 d = min(d, e[pe[v]].cap); 129 f -= d; 130 ret += d * dist[t]; 131 for(int v = t; v != s; v = pv[v]) 132 { 133 e[pe[v]].cap -= d; 134 e[pe[v]^1].cap += d; 135 } 136 } 137 return ret; 138 } 139 140 141 int main(void) 142 { 143 int T; 144 scanf("%d", &T); 145 while(T--) 146 { 147 int m; 148 scanf("%d %d", &n, &m); 149 char s[555]; 150 scanf("%s", s + 1); 151 for(int i = 1; i <= n; i++) cl[i] = s[i] - '0'; 152 for(int i = 1; i <= n; i++) 153 for(int j = 1; j <= n; j++) 154 G[i][j] = i == j ? 0 : INF; 155 for(int i = 1; i <= m; i++) 156 { 157 int u, v; 158 scanf("%d %d", &u, &v); 159 G[u][v] = G[v][u] = 1; 160 } 161 162 Floyd(); 163 164 int ok = 1, ans = 0; 165 tmp.clear(); 166 memset(id, 0, sizeof(id)); 167 memset(used, 0, sizeof(used)); 168 for(int i = 1; i <= n; i++) 169 { 170 if(used[i]) continue; 171 172 c0 = c1 = n0 = n1 = 0; 173 if(!draw(i, 0, i)) {ok = 0; break;} 174 175 if(c0 == c1 && n0 == n1) 176 { 177 init(); 178 int f = 0; 179 int S = n + 1, T = S + 1; 180 for(int u = 1; u <= n; u++) 181 { 182 if(id[u] != i) continue; 183 if(cl[u] == nc[u]) continue; 184 185 if(cl[u]) 186 { 187 ad(S, u, 1, 0), f++; 188 for(int v = 1; v <= n; v++) 189 { 190 if(id[v] != i) continue; 191 if(cl[v] == nc[v] || cl[u] == cl[v]) continue; 192 ad(u, v, 1, G[u][v]); 193 } 194 } 195 else ad(u, T, 1, 0); 196 } 197 198 int flow1 = min_cost_flow(S, T, f); 199 v1.clear(); 200 for(int u = 1; u <= n; u++) 201 { 202 if(id[u] != i) continue; 203 if(cl[u] == nc[u] || !cl[u]) continue; 204 for(int j = h[u]; j >= 0; j = e[j].pre) 205 if(e[j].to != S && !e[j].cap) v1.push_back(pii(u, e[j].to)); 206 } 207 208 init(), flip(i), f = 0; 209 for(int u = 1; u <= n; u++) 210 { 211 if(id[u] != i) continue; 212 if(cl[u] == nc[u]) continue; 213 214 if(cl[u]) 215 { 216 ad(S, u, 1, 0), f++; 217 for(int v = 1; v <= n; v++) 218 { 219 if(id[v] != i) continue; 220 if(cl[v] == nc[v] || cl[u] == cl[v]) continue; 221 ad(u, v, 1, G[u][v]); 222 } 223 } 224 else ad(u, T, 1, 0); 225 } 226 227 int flow2 = min_cost_flow(S, T, f); 228 v2.clear(); 229 for(int u = 1; u <= n; u++) 230 { 231 if(id[u] != i) continue; 232 if(cl[u] == nc[u] || !cl[u]) continue; 233 for(int j = h[u]; j >= 0; j = e[j].pre) 234 if(e[j].to != S && !e[j].cap) v2.push_back(pii(u, e[j].to)); 235 } 236 237 if(flow1 <= flow2) 238 { 239 ans += flow1; 240 flip(i); 241 int sz = v1.size(); 242 for(int j = 0; j < sz; j++) 243 { 244 int u = v1[j].first, v = v1[j].second; 245 path.clear(), get_path(u, v); 246 int sp = path.size(), last = 0; 247 for(int k = 0; k < sp; k++) 248 if(cl[path[k].first] != cl[path[k].second]) 249 { 250 for(int r = k; r >= last; r--) 251 { 252 tmp.push_back(path[r]); 253 swap(cl[path[r].first], cl[path[r].second]); 254 } 255 last = k + 1; 256 } 257 } 258 } 259 else 260 { 261 ans += flow2; 262 int sz = v2.size(); 263 for(int j = 0; j < sz; j++) 264 { 265 int u = v2[j].first, v = v2[j].second; 266 path.clear(), get_path(u, v); 267 int sp = path.size(), last = 0; 268 for(int k = 0; k < sp; k++) 269 if(cl[path[k].first] != cl[path[k].second]) 270 { 271 for(int r = k; r >= last; r--) 272 { 273 tmp.push_back(path[r]); 274 swap(cl[path[r].first], cl[path[r].second]); 275 } 276 last = k + 1; 277 } 278 } 279 } 280 281 } 282 283 else if(c0 == n0 && c1 == n1) 284 { 285 init(); 286 int f = 0; 287 int S = n + 1, T = S + 1; 288 for(int u = 1; u <= n; u++) 289 { 290 if(id[u] != i) continue; 291 if(cl[u] == nc[u]) continue; 292 293 if(cl[u]) 294 { 295 ad(S, u, 1, 0), f++; 296 for(int v = 1; v <= n; v++) 297 { 298 if(id[v] != i) continue; 299 if(cl[v] == nc[v] || cl[u] == cl[v]) continue; 300 ad(u, v, 1, G[u][v]); 301 } 302 } 303 else ad(u, T, 1, 0); 304 } 305 306 int flow1 = min_cost_flow(S, T, f); 307 v1.clear(); 308 for(int u = 1; u <= n; u++) 309 { 310 if(id[u] != i) continue; 311 if(cl[u] == nc[u] || !cl[u]) continue; 312 for(int j = h[u]; j >= 0; j = e[j].pre) 313 if(e[j].to != S && !e[j].cap) v1.push_back(pii(u, e[j].to)); 314 } 315 316 ans += flow1; 317 int sz = v1.size(); 318 for(int j = 0; j < sz; j++) 319 { 320 int u = v1[j].first, v = v1[j].second; 321 path.clear(), get_path(u, v); 322 int sp = path.size(), last = 0; 323 for(int k = 0; k < sp; k++) 324 if(cl[path[k].first] != cl[path[k].second]) 325 { 326 for(int r = k; r >= last; r--) 327 { 328 tmp.push_back(path[r]); 329 swap(cl[path[r].first], cl[path[r].second]); 330 } 331 last = k + 1; 332 } 333 } 334 335 } 336 337 else if(c0 == n1 && c1 == n0) 338 { 339 init(), flip(i); 340 int f = 0; 341 int S = n + 1, T = S + 1; 342 for(int u = 1; u <= n; u++) 343 { 344 if(id[u] != i) continue; 345 if(cl[u] == nc[u]) continue; 346 347 if(cl[u]) 348 { 349 ad(S, u, 1, 0), f++; 350 for(int v = 1; v <= n; v++) 351 { 352 if(id[v] != i) continue; 353 if(cl[v] == nc[v] || cl[u] == cl[v]) continue; 354 ad(u, v, 1, G[u][v]); 355 } 356 } 357 else ad(u, T, 1, 0); 358 } 359 360 int flow2 = min_cost_flow(S, T, f); 361 v2.clear(); 362 for(int u = 1; u <= n; u++) 363 { 364 if(id[u] != i) continue; 365 if(cl[u] == nc[u] || !cl[u]) continue; 366 for(int j = h[u]; j >= 0; j = e[j].pre) 367 if(e[j].to != S && !e[j].cap) v2.push_back(pii(u, e[j].to)); 368 } 369 370 ans += flow2; 371 int sz = v2.size(); 372 for(int j = 0; j < sz; j++) 373 { 374 int u = v2[j].first, v = v2[j].second; 375 path.clear(), get_path(u, v); 376 int sp = path.size(), last = 0; 377 for(int k = 0; k < sp; k++) 378 if(cl[path[k].first] != cl[path[k].second]) 379 { 380 for(int r = k; r >= last; r--) 381 { 382 tmp.push_back(path[r]); 383 swap(cl[path[r].first], cl[path[r].second]); 384 } 385 last = k + 1; 386 } 387 } 388 389 } 390 391 else {ok = 0; break;} 392 393 } 394 395 396 if(!ok) puts("-1"); 397 else 398 { 399 printf("%d\n", ans); 400 int sz = tmp.size(); 401 for(int i = 0; i < sz; i++) printf("%d %d\n", tmp[i].first, tmp[i].second); 402 } 403 404 } 405 return 0; 406 }
1008 Helter Skelter
据说可行域是连续区间而且一维随另一维单调不减而且转折点都是01分界点哦。
1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <algorithm> 5 using namespace std; 6 typedef pair<int, int> pii; 7 const int INF = 2e9; 8 const int maxn = 1e6 + 10; 9 int x[1111]; 10 vector<pii> z, o; 11 pii stz[maxn], sto[maxn]; 12 char ans[maxn]; 13 14 int main(void) 15 { 16 int T; 17 scanf("%d", &T); 18 while(T--) 19 { 20 int n, m; 21 scanf("%d %d", &n, &m); 22 for(int i = 1; i <= n; i++) scanf("%d", x + i); 23 24 z.clear(), o.clear(); 25 for(int i = 1; i <= n; i++) 26 { 27 int c0 = 0, c1 = 0; 28 for(int j = i; j <= n; j++) 29 { 30 if(j % 2) c0 += x[j]; 31 else c1 += x[j]; 32 if(j % 2 == 1 && i % 2 == 1) z.push_back(pii(c0, c1)); 33 if(j % 2 == 0 && i % 2 == 0) o.push_back(pii(c0, c1)); 34 } 35 } 36 37 sort(z.begin(), z.end()); 38 sort(o.begin(), o.end()); 39 40 int sz = z.size(), so = o.size(); 41 int pz = 0, po = 0; 42 43 for(int i = 0; i < sz; i++) 44 { 45 if(i && z[i].first == z[i-1].first) continue; 46 while(pz && stz[pz].second >= z[i].second) pz--; 47 stz[++pz] = z[i]; 48 } 49 50 for(int i = 0; i < so; i++) 51 { 52 if(i < so - 1 && o[i].first == o[i+1].first) continue; 53 if(!po || o[i].second > sto[po].second) sto[++po] = o[i]; 54 } 55 56 for(int i = 0; i < m; i++) 57 { 58 int a, b; 59 scanf("%d %d", &a, &b); 60 int l = lower_bound(stz + 1, stz + 1 + pz, pii(a, 0)) - stz; 61 int u = lower_bound(sto + 1, sto + 1 + po, pii(a, INF)) - sto - 1; 62 if(l < pz + 1 && b >= stz[l].second && b <= sto[u].second) ans[i] = '1'; 63 else ans[i] = '0'; 64 } 65 ans[m] = 0; 66 puts(ans); 67 } 68 return 0; 69 }
1009 It's All In The Mind
1010 Join The Future
1011 Keep On Movin
1012 La Vie en rose
1013 Memento Mori