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 }
Aguin

 

1003 Call It What You Want

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 }
Aguin

 

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;
}
Aguin

 

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 }
Aguin

 

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 }
Aguin

 

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 }
Aguin

 

1009 It's All In The Mind

1010 Join The Future

1011 Keep On Movin

1012 La Vie en rose

1013 Memento Mori

posted @ 2016-07-21 21:28  Aguin  阅读(223)  评论(1编辑  收藏  举报