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

// Problem Decorate the wall

// Algorithm brute force


// 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
// is a possible solution. Since the
iteration is done
// in increasing order of y, then x, it is
the desired solution
cout << *it << " " << *it2 << endl;
goto done;
}
}
}
}
cout << "Fail!" << endl;
done:;
}
string s;
assert(!(in >> s));
return 0;
}

// Problem Decorate the wall


// Algorithm interval compression, scanline
// 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;
}

Вам также может понравиться