Вы находитесь на странице: 1из 4

// Problem

// Algorithm brute force

Decorate the wall

// Runtime

O(n^3)

// Author

Adrian Kuegel

// Date

2005.05.28

#define MAXN 256

typedef set<int> SI;

int main() { int tc; ifstream in("decorate.in"); in >> tc; while(tc-- > 0) { int n,w,h; in >> n >> w >> h; assert(n>=0 && n<=200 && w>=1 && h>=1 && w<=1000000 && h<=1000000); int x1[MAXN],y1[MAXN],x2[MAXN],y2[MAXN]; // store all necessary x and y-values in a set // note that only boundary coordinates are required // The new painting must be bounded at the bottom and the left;

otherwise,

// there would be another position where it fits which is preferred SI allx, ally;

allx.insert(0);

ally.insert(0);

// read the already hanging paintings for (int i=0; i<n; i++) { in >> x1[i] >> y1[i] >> x2[i] >> y2[i]; assert(x1[i]<x2[i] && x1[i]>=0 && x2[i]<=w); assert(y1[i]<y2[i] && y1[i]>=0 && y2[i]<=h); // assert that there are no overlapping paintings for (int j=0; j<i; j++)

assert(max(x1[i],x1[j])>=min(x2[i],x2[j])

|| max(y1[i],y1[j])>=min(y2[i],y2[j]));

allx.insert(x1[i]);

allx.insert(x2[i]);

ally.insert(y1[i]);

ally.insert(y2[i]);

}

int needed_w, needed_h; in >> needed_w >> needed_h; assert(needed_w > 0 && needed_w <= w && needed_h > 0 && needed_h <= h); // brute force over possible lower left corners for (SI::iterator it2 = ally.begin(); it2 != ally.end(); it2++) {

if (*it2 + needed_h > h) break; for (SI::iterator it = allx.begin(); it!=allx.end(); it++) { if (*it + needed_w > w) break; // check if there are any overlappings if current lower left

corner is used

for (int i=0; i<n; i++) { if (max(x1[i],*it)<min(x2[i],*it+needed_w) && max(y1[i],*it2)<min(y2[i],*it2+needed_h)) break; if (i == n-1) { // if no already hanging painting

overlaps, the corner

iteration is done

the desired solution

// is a possible solution. Since the

// in increasing order of y, then x, it is

}

cout << *it << " " << *it2 << endl; goto done;

}

}

}

}

cout << "Fail!" << endl; done:;

}

string s; assert(!(in >> s));

return 0;

Decorate the wall

// Algorithm interval compression, scanline

// Problem

// Runtime

O(n^2)

// Author

Adrian Kuegel

// Date

2005.05.28

#define MAXN 256

typedef map<int,int> MII; typedef vector<int> VI;

int main() { int tc;

ifstream in("decorate.in"); in >> tc; while(tc-- > 0) {

int n,w,h;

in >> n >> w >> h; assert(n>=0 && n<=200 && w>=1 && h>=1 && w<=1000000 && h<=1000000);

int x1[MAXN],y1[MAXN],x2[MAXN],y2[MAXN];

// store all necessary x and y-values in a map // note that only boundary coordinates are required // The new painting must be bounded at the bottom and the left;

otherwise,

// there would be another position where it fits which is preferred

MII allx, ally;

allx[0] = ally[0] = 0; allx[w] = ally[h] = 0; // read the already hanging paintings for (int i=0; i<n; i++) { in >> x1[i] >> y1[i] >> x2[i] >> y2[i]; assert(x1[i]<x2[i] && x1[i]>=0 && x2[i]<=w); assert(y1[i]<y2[i] && y1[i]>=0 && y2[i]<=h); // assert that there are no overlapping paintings for (int j=0; j<i; j++)

assert(max(x1[i],x1[j])>=min(x2[i],x2[j])

|| max(y1[i],y1[j])>=min(y2[i],y2[j])); // first, assign each coordinate a dummy value

// later, relabel them in order allx[x1[i]] = allx[x2[i]] = 0; ally[y1[i]] = ally[y2[i]] = 0;

}

int

needed_w, needed_h;

int

best_x = w,best_y = h;

in >> needed_w >> needed_h; assert(needed_w > 0 && needed_w <= w && needed_h > 0 && needed_h <= h); // now relabel the x-values such that smallest x-value is 0, largest is

allx.size()-1

int label = 0; for (MII::iterator it=allx.begin(); it!=allx.end(); it++) it->second = label++; int neww = label-1;

// now relabel the y-values such that smallest y-value is 0, largest is

ally.size()-1

label = 0; for (MII::iterator it=ally.begin(); it!=ally.end(); it++) it->second = label++; int newh = label-1; assert(neww < MAXN*2+2 && newh < MAXN*2 + 2);

VI top_of_painting[MAXN*2 + 2];

for (int i=0; i<n; i++) { // use the new labels instead of old y-values // for each upper boundary of a painting, store the index of the

painting

top_of_painting[ally[y2[i]]].push_back(i);

}

//

use a scanline algorithm over y-values in descending order

MII::iterator cur_height = ally.end();

// for each x-value, store the y-value of the last time this place was

covered

int last_covered[MAXN*2 + 2]; for (int i=0; i<=neww; i++) last_covered[i] = h; for (int i=newh; i>=0; i--) { --cur_height; // last x-value with required height available int last = 0; // linear scan through all x-values for (MII::iterator it = allx.begin(); it != allx.end();) { // check if the required width is available if (it->first - last >= needed_w) { // update best solution if (cur_height->first < best_y || cur_height->first ==

best_y && last < best_x) {

}

}

best_y = cur_height->first; best_x = last;

int height_available = last_covered[it->second] -

cur_height->first;

it++; // if there is not enough height available, update left

boundary

if (height_available<needed_h && it != allx.end()) last = it->first;

}

// insert the ranges of pictures which are beginning at the

current height

for (VI::iterator it = top_of_painting[i].begin(); it != top_of_painting[i].end(); it++) { int end = allx[x2[*it]]; // update last_covered with the value when the painting ends

(bottom boundary)

// since there are only O(n) different x-values in allx,

this loop runs in O(n)

// this loop is executed exactly once for each painting, so overall O(n^2) complexity for (int i=allx[x1[*it]]; i<end; i++) last_covered[i] = y1[*it];

}

}

if (best_x == w && best_y == h)

cout << "Fail!" << endl;

else

cout << best_x << " " << best_y << endl;

}

return 0;

}

#include <cstdio> #include <cstring> #define N 30005

int fa[N], rank[N], root[N]; void init_set(int n) { for (int i = 0; i <= n; i++) root[i] = fa[i] = i, rank[i] = 0;

}

int find_root(int p) { if (fa[p] != p) fa[p] = find_root(fa[p]); return fa[p];

}

void union_set(int p, int q) { int a = find_root(p), b = find_root(q); if (a == b) return; if (rank[a] > rank[b]) fa[b] = a; else if (rank[a] < rank[b]) fa[a] = b; else fa[b] = a, rank[a]++;

}

int main() { int n; while (scanf("%d\n", &n) != EOF) { int p = n + 1, a, b; int n1, n2; char op; n1 = n2 = 0; init_set(n); while (1) { scanf("%c", &op); if (op == 'e') { printf("%d , %d\n", n1, n2); break;

} else if (op == 'c') { scanf("%d%d\n", &a, &b); union_set(root[a], root[b]);

} else if (op == 'd') { scanf("%d\n", &a); root[a] = p++; rank[root[a]] = 0; fa[root[a]] = root[a];

} else if (op == 'q') { scanf("%d%d\n", &a, &b); a = root[a], b = root[b]; if (find_root(a) == find_root(b))

{/*printf("Yes\n");*/n1++;}

else {/*printf("No\n");*/n2++;}

}

}

}

}

return 0;