#include <bits/stdc++.h> using namespace std; typedef long long ll; #define M 100007 // From EPFL/UWr library #define N 2007 void add (ll *a, int n, ll x) { // val[n] += x for (; n < N; n |= n+1) a[n] += x; } ll sum (ll *a, int n) { // val[0] + val[1] + ... + val[n] ll s = 0; while (n >= 0) { s += a[n]; n = (n&(n+1))-1; } return s; } // RANGE QUERIES + RANGE UPDATES ll tadd[N], tmul[N]; void addOnSegment (int le, int ri, ll x) { // add to [le..ri]: [x,x,...,x] add(tmul, le, x); add(tadd, le, -x * (le-1)); add(tmul, ri, -x); add(tadd, ri, x * ri); } ll query (int n) { // get sum[0..n] return sum(tadd,n) + sum(tmul,n) * n; } #define REP(i,a,b) for (int i = (a); i <= (b); ++i) #define REPD(i,a,b) for (int i = (a); i >= (b); --i) #define FORI(i,n) REP(i,1,n) #define FOREACH(i,t) for (__typeof(t.begin()) i = t.begin(); i != t.end(); ++i) int nn,mm; vector<int> adj[N*N]; int ppair[N*N]; bool vis[N*N]; bool augment (int v) { // 1 <= v <= nn (lub v = -1) if (v == -1) return 1; if (vis[v]) return 0; else{ vis[v] = true; } FOREACH(x,adj[v]) { if (augment(ppair[*x])) { ppair[*x] = v; ppair[v] = *x; return 1; } } return 0; } // vertices on the left should have numbers 1..nn, on the right - nn+1..nn+mm // PRE: set nn,mm,adj (adj needs to be filled out only for vertices 1..nn), and // the constant MAXV = maximum nn+mm int matching () { FORI(i,nn+mm) ppair[i] = -1; int w = 0; FORI(i,nn) { FORI(j,nn) vis[j] = 0; w += augment(i); } return w; } int tab[N][N], n, m, q, a, b; #define X1 1 #define Y1 0 #define X2 3 #define Y2 2 int quad[M][4]; int empty_numbering[N][N]; int main(){ scanf("%d%d%d", &n, &m, &q); for(int i = 0; i < m; i++){ // xx1, yy1, xx2, yy2 for(int r =0; r <4; r++){ scanf("%d", &quad[i][r]); quad[i][r]--; } } // A total abuse of this DS. for(int x = 0; x < n; x++){ for(int y = 0; y < n; y++){ tadd[y] = 0; tmul[y] = 0; } for(int i = 0; i < m; i++){ if (quad[i][X1] > x || quad[i][X2] < x) continue; addOnSegment(quad[i][Y1], quad[i][Y2], 1ll); } for(int y = 0; y < n; y++){ if (y){ tab[x][y] = query(y) - query(y-1); } else { tab[x][y] = query(y); } } } for(int i = 0; i<= q;i++){ /* for(int y = 0; y < n; y++){ for(int x = 0; x < n; x++){ if ((tab[x][y] % 2) == 0) printf("."); else printf("X"); } printf("\n"); }*/ for(int i = 0; i <=nn;i++){ adj[i].clear(); } nn = 1; mm = 0; for(int y=0; y<n;y++){ for(int x =0; x <n;x++){ if (!(tab[x][y] % 2)){ empty_numbering[x][y] = mm; mm++; } }} // TODO(sygi): update graph faster: it's not changing a lot. for(int y = 0; y < n; y++){ for(int x = 0; x < n; x++){ if (tab[x][y] % 2){ for(int another_x = 0; another_x < n; another_x++){ if (!(tab[another_x][y] % 2)){ adj[nn].push_back(empty_numbering[another_x][y]); } } for(int another_y = 0; another_y < n; another_y++){ if (!(tab[x][another_y] % 2)){ adj[nn].push_back(empty_numbering[x][another_y]); } } nn++; } else { mm++; } } } nn--; for(int i = 1; i <= nn; i++){ // printf("adj %d:", i); for(int j = 0; j < adj[i].size(); j++){ adj[i][j] += nn; // printf("%d ",adj[i][j]); } // printf("\n"); } //printf("%d with %d without\n", nn, mm); printf("%d\n", matching()); if(i!=q){ scanf("%d%d", &b, &a); a--;b--; tab[a][b]++; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | #include <bits/stdc++.h> using namespace std; typedef long long ll; #define M 100007 // From EPFL/UWr library #define N 2007 void add (ll *a, int n, ll x) { // val[n] += x for (; n < N; n |= n+1) a[n] += x; } ll sum (ll *a, int n) { // val[0] + val[1] + ... + val[n] ll s = 0; while (n >= 0) { s += a[n]; n = (n&(n+1))-1; } return s; } // RANGE QUERIES + RANGE UPDATES ll tadd[N], tmul[N]; void addOnSegment (int le, int ri, ll x) { // add to [le..ri]: [x,x,...,x] add(tmul, le, x); add(tadd, le, -x * (le-1)); add(tmul, ri, -x); add(tadd, ri, x * ri); } ll query (int n) { // get sum[0..n] return sum(tadd,n) + sum(tmul,n) * n; } #define REP(i,a,b) for (int i = (a); i <= (b); ++i) #define REPD(i,a,b) for (int i = (a); i >= (b); --i) #define FORI(i,n) REP(i,1,n) #define FOREACH(i,t) for (__typeof(t.begin()) i = t.begin(); i != t.end(); ++i) int nn,mm; vector<int> adj[N*N]; int ppair[N*N]; bool vis[N*N]; bool augment (int v) { // 1 <= v <= nn (lub v = -1) if (v == -1) return 1; if (vis[v]) return 0; else{ vis[v] = true; } FOREACH(x,adj[v]) { if (augment(ppair[*x])) { ppair[*x] = v; ppair[v] = *x; return 1; } } return 0; } // vertices on the left should have numbers 1..nn, on the right - nn+1..nn+mm // PRE: set nn,mm,adj (adj needs to be filled out only for vertices 1..nn), and // the constant MAXV = maximum nn+mm int matching () { FORI(i,nn+mm) ppair[i] = -1; int w = 0; FORI(i,nn) { FORI(j,nn) vis[j] = 0; w += augment(i); } return w; } int tab[N][N], n, m, q, a, b; #define X1 1 #define Y1 0 #define X2 3 #define Y2 2 int quad[M][4]; int empty_numbering[N][N]; int main(){ scanf("%d%d%d", &n, &m, &q); for(int i = 0; i < m; i++){ // xx1, yy1, xx2, yy2 for(int r =0; r <4; r++){ scanf("%d", &quad[i][r]); quad[i][r]--; } } // A total abuse of this DS. for(int x = 0; x < n; x++){ for(int y = 0; y < n; y++){ tadd[y] = 0; tmul[y] = 0; } for(int i = 0; i < m; i++){ if (quad[i][X1] > x || quad[i][X2] < x) continue; addOnSegment(quad[i][Y1], quad[i][Y2], 1ll); } for(int y = 0; y < n; y++){ if (y){ tab[x][y] = query(y) - query(y-1); } else { tab[x][y] = query(y); } } } for(int i = 0; i<= q;i++){ /* for(int y = 0; y < n; y++){ for(int x = 0; x < n; x++){ if ((tab[x][y] % 2) == 0) printf("."); else printf("X"); } printf("\n"); }*/ for(int i = 0; i <=nn;i++){ adj[i].clear(); } nn = 1; mm = 0; for(int y=0; y<n;y++){ for(int x =0; x <n;x++){ if (!(tab[x][y] % 2)){ empty_numbering[x][y] = mm; mm++; } }} // TODO(sygi): update graph faster: it's not changing a lot. for(int y = 0; y < n; y++){ for(int x = 0; x < n; x++){ if (tab[x][y] % 2){ for(int another_x = 0; another_x < n; another_x++){ if (!(tab[another_x][y] % 2)){ adj[nn].push_back(empty_numbering[another_x][y]); } } for(int another_y = 0; another_y < n; another_y++){ if (!(tab[x][another_y] % 2)){ adj[nn].push_back(empty_numbering[x][another_y]); } } nn++; } else { mm++; } } } nn--; for(int i = 1; i <= nn; i++){ // printf("adj %d:", i); for(int j = 0; j < adj[i].size(); j++){ adj[i][j] += nn; // printf("%d ",adj[i][j]); } // printf("\n"); } //printf("%d with %d without\n", nn, mm); printf("%d\n", matching()); if(i!=q){ scanf("%d%d", &b, &a); a--;b--; tab[a][b]++; } } } |