离线强化训练

10.17

HYSBZ - 4999

看似在线,实际每个数字独立,可以每种数字拆出来考虑,转变为树上单点修改询问链。

维护差分,变为子树修改,单点询问,排好dfs序后用线段树维护。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <vector>
  4 #include <algorithm>
  5 #include <set>
  6 using namespace std;
  7 const int maxn = 1e5 + 10;
  8 int a[maxn], c[maxn];
  9 vector<int> b, g[maxn];
 10 int op[200005], I[200005], J[200005], X[200005], ans[200005];
 11 
 12 typedef pair<int, int> pii;
 13 vector<pii> q[300005];
 14 set<int> S;
 15 set<int> :: iterator it;
 16 
 17 // LCA
 18 int dfs_clock = 0;
 19 int dep[maxn], l[maxn], r[maxn];
 20 int anc[maxn][33];
 21 void dfs(int x, int fa)
 22 {
 23     l[x] = r[x] = ++dfs_clock;
 24     for(int i = 0; i < g[x].size(); i++)
 25     {
 26         int to = g[x][i];
 27         if(to == fa) continue;
 28         dep[to] = dep[x] + 1;
 29         anc[to][0] = x;
 30         dfs(to, x);
 31         r[x] = r[to];
 32     }
 33 }
 34 void LCA_init(int n)
 35 {
 36     for(int j = 1; (1 << j) < n; j++)
 37         for(int i = 1; i <= n; i++) if(anc[i][j-1])
 38             anc[i][j] = anc[anc[i][j-1]][j-1];
 39 }
 40 int LCA(int u, int v)
 41 {
 42     int log;
 43     if(dep[u] < dep[v]) swap(u, v);
 44     for(log = 0; (1 << log) < dep[u]; log++);
 45     for(int i = log; i >= 0; i--)
 46         if(dep[u] - (1<<i) >= dep[v]) u = anc[u][i];
 47     if(u == v) return u;
 48     for(int i = log; i >= 0; i--)
 49         if(anc[u][i] && anc[u][i] != anc[v][i])
 50             u = anc[u][i], v = anc[v][i];
 51     return anc[u][0];
 52 }
 53 
 54 // segment_tree
 55 int tag[maxn<<2];
 56 void modify(int p, int tl, int tr, int l, int r, int x)
 57 {
 58     if(tr < l || r < tl) return;
 59     if(l <= tl && tr <= r)
 60     {
 61         tag[p] += x;
 62         return;
 63     }
 64     int mid = (tl + tr) >> 1;
 65     modify(p<<1, tl, mid, l, r, x);
 66     modify(p<<1|1, mid+1, tr, l, r, x);
 67 }
 68 int query(int p, int tl, int tr, int x)
 69 {
 70     if(x == 0) return 0;
 71     int ret = tag[p];
 72     if(tl == tr) return ret;
 73     int mid = (tl + tr) >> 1;
 74     if(x <= mid) ret += query(p<<1, tl, mid, x);
 75     else ret += query(p<<1|1, mid+1, tr, x);
 76     return ret;
 77 }
 78 
 79 int main(void)
 80 {
 81     int N, Q;
 82     scanf("%d %d", &N, &Q);
 83     for(int i = 1; i <= N; i++) scanf("%d", a + i), b.push_back(a[i]);
 84     for(int i = 1; i < N; i++)
 85     {
 86         int u, v;
 87         scanf("%d %d", &u, &v);
 88         g[u].push_back(v);
 89         g[v].push_back(u);
 90     }
 91     for(int i = 1; i <= Q; i++)
 92     {
 93         char s[11];
 94         scanf("%s", s);
 95         if(s[0] == 'C')
 96         {
 97             op[i] = 1;
 98             scanf("%d %d", I + i, X + i);
 99         }
100         else
101         {
102             op[i] = 2;
103             scanf("%d %d %d", I + i, J + i, X + i);
104         }
105         b.push_back(X[i]);
106     }
107     sort(b.begin(), b.end());
108     b.erase(unique(b.begin(), b.end()), b.end());
109     for(int i = 1; i <= N; i++) a[i] = lower_bound(b.begin(), b.end(), a[i]) - b.begin() + 1;
110     for(int i = 1; i <= Q; i++) X[i] = lower_bound(b.begin(), b.end(), X[i]) - b.begin() + 1;
111     for(int i = 1; i <= N; i++) c[i] = a[i], q[c[i]].push_back(pii(1, i));
112     for(int i = 1; i <= Q; i++)
113     {
114         if(op[i] == 1)
115         {
116             q[c[I[i]]].push_back(pii(-1, I[i]));
117             q[X[i]].push_back(pii(1, I[i]));
118             c[I[i]] = X[i];
119         }
120         else q[X[i]].push_back(pii(0, i));
121     }
122     dfs(1, 0);
123     LCA_init(N);
124     for(int i = 1; i <= b.size(); i++)
125     {
126         for(int j = 0; j < q[i].size(); j++)
127         {
128             int x = q[i][j].first, y = q[i][j].second;
129             if(x == 1) modify(1, 1, N, l[y], r[y], 1), S.insert(y);
130             if(x == -1) modify(1, 1, N, l[y], r[y], -1), S.erase(y);
131             if(x == 0) ans[y] = query(1, 1, N, l[I[y]]) + query(1, 1, N, l[J[y]]) - query(1, 1, N, l[LCA(I[y], J[y])]) - query(1, 1, N, l[anc[LCA(I[y], J[y])][0]]);
132         }
133         for(it = S.begin(); it != S.end(); it++) modify(1, 1, N, l[*it], r[*it], -1);
134         S.clear();
135     }
136     for(int i = 1; i <= Q; i++)
137         if(op[i] == 2) printf("%d\n", ans[i]);
138     return 0;
139 }
Aguin

10.19

HYSBZ - 1453

按时间分治带撤销并查集还是直接线段树暴力并查集吧。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 using namespace std;
  6 const int maxn = 205;
  7 int G[maxn][maxn];
  8 int x[11111], y[11111];
  9 int n, m;
 10 
 11 int fa[808], tmp[808];
 12 int Find(int x)
 13 {
 14     return fa[x] == x ? x : fa[x] = Find(fa[x]);
 15 }
 16 inline void Union(int x, int y)
 17 {
 18     x = Find(x), y = Find(y);
 19     if(x < y) swap(x, y);
 20     fa[x] = y;
 21 }
 22 int L[maxn<<2][maxn], R[maxn<<2][maxn], sum[maxn<<2][2];
 23 inline void gather(int p, int tl, int tr)
 24 {
 25     sum[p][0] = sum[p<<1][0] + sum[p<<1|1][0];
 26     sum[p][1] = sum[p<<1][1] + sum[p<<1|1][1];
 27     for(int i = 1; i <= n; i++)
 28     {
 29         fa[i] = L[p<<1][i];
 30         fa[i+n] = R[p<<1][i];
 31         fa[i+n+n] = n + n + L[p<<1|1][i];
 32         fa[i+n+n+n] = n + n + R[p<<1|1][i];
 33         tmp[i] = tmp[i+n] = tmp[i+n+n] = tmp[i+n+n+n] = 0;
 34     }
 35     int mid = (tl + tr) >> 1;
 36     for(int i = 1; i <= n; i++)
 37         if(G[mid][n-i+1] == G[mid+1][n-i+1] && Find(i+n) != Find(i+n+n))
 38             Union(i + n, i + n + n), sum[p][G[mid][n-i+1]]--;
 39     for(int i = 1; i <= n; i++)
 40         L[p][i] = Find(i), R[p][i] = Find(i+n+n+n);
 41     for(int i = 1; i <= n; i++)
 42     {
 43         if(R[p][i] <= n) continue;
 44         if(tmp[R[p][i]]) R[p][i] = tmp[R[p][i]];
 45         else tmp[R[p][i]] = n + i, R[p][i] = n + i;
 46     }
 47 }
 48 void build(int p, int tl, int tr)
 49 {
 50     if(tl == tr)
 51     {
 52         sum[p][0] = sum[p][1] = 0;
 53         for(int i = 1; i <= n; i++)
 54         {
 55             if(i != 1 && G[tl][n-i+1] == G[tl][n-i+2]) L[p][i] = R[p][i] = L[p][i-1];
 56             else L[p][i] = R[p][i] = i, sum[p][G[tl][n-i+1]]++;
 57         }
 58         return;
 59     }
 60     int mid = (tl + tr) >> 1;
 61     build(p<<1, tl, mid);
 62     build(p<<1|1, mid+1, tr);
 63     gather(p, tl, tr);
 64 }
 65 void modify(int p, int tl, int tr, int x)
 66 {
 67     if(tl == tr)
 68     {
 69         sum[p][0] = sum[p][1] = 0;
 70         for(int i = 1; i <= n; i++)
 71         {
 72             if(i != 1 && G[tl][n-i+1] == G[tl][n-i+2]) L[p][i] = R[p][i] = L[p][i-1];
 73             else L[p][i] = R[p][i] = i, sum[p][G[tl][n-i+1]]++;
 74         }
 75         return;
 76     }
 77     int mid = (tl + tr) >> 1;
 78     if(x <= mid) modify(p<<1, tl, mid, x);
 79     else modify(p<<1|1, mid+1, tr, x);
 80     gather(p, tl, tr);
 81 }
 82 
 83 int main(void)
 84 {
 85     scanf("%d", &n);
 86     for(int i = 1; i <= n; i++)
 87         for(int j = 1; j <= n; j++)
 88             scanf("%d", &G[i][j]);
 89     build(1, 1, n);
 90     scanf("%d", &m);
 91     for(int i = 1; i <= m; i++)
 92     {
 93         scanf("%d %d", x + i, y + i);
 94         G[x[i]][y[i]] ^= 1;
 95         modify(1, 1, n, x[i]);
 96         printf("%d %d\n", sum[1][1], sum[1][0]);
 97     }
 98     return 0;
 99 }
100 /*
101 5
102 0 1 0 0 0
103 0 1 1 1 0
104 1 0 0 0 1
105 0 0 1 0 0
106 1 0 0 0 0
107 2
108 3 2
109 2 3
110 */
Aguin

 

posted @ 2017-10-17 22:52  Aguin  阅读(374)  评论(0编辑  收藏  举报