# Atcoder beginer contest 223 (supplementary question)

## Meaning:

Given a parenthesized string, there are now two operations
Operation 1: given l,r, exchange the characters of l,r
Operation 2: given L and R, query whether the parentheses of this interval are legal

## Idea:

(defined as + 1,) defined as - 1. For the original string, maintain a prefix and
If the [l,r] interval of the query operation is legal, the sum of this interval must be 0, representing the overall matching, and each value in the prefix sum of the interval must be > = 0 >=0 >=0, representing the matching of each inner bracket.
To simplify, the minimum value of prefix sum in the interval must be > = 0, and the interval sum must be = 0

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
string s;
int a[N];
int sum[N];
struct node {
int l, r;
int minv;
} tr[N * 4];
int n, m;
void pushup(int u) { tr[u].minv = min(tr[u << 1].minv, tr[u << 1 | 1].minv); }

void pushdown(int u) {
tr[u << 1 | 1].add += tr[u].add;
tr[u << 1].minv += tr[u].add;
tr[u << 1 | 1].minv += tr[u].add;
}
}
void build(int u, int l, int r) {
if (l == r) {
tr[u] = {l, r};
return;
}
tr[u].l = l, tr[u].r = r;
int mid = l + r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}

void modify(int u, int l, int r, int x) {
if (tr[u].l >= l && tr[u].r <= r) {
tr[u].minv += x;
return;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if (l <= mid) modify(u << 1, l, r, x);
if (r > mid) modify(u << 1 | 1, l, r, x);
pushup(u);
}

int query(int u, int l, int r) {
if (l <= tr[u].l && tr[u].r <= r) {
return tr[u].minv;
}
int mid = tr[u].l + tr[u].r >> 1;
pushdown(u);
int res = 1e9;
if (l <= mid) res = min(res, query(u << 1, l, r));
if (r > mid) res = min(res, query(u << 1 | 1, l, r));
return res;
}

int main() {
cin >> n >> m;
cin >> s;
int len = s.size();
for (int i = 0; i < n; i++) {
if (s[i] == '(')
a[i + 1] = 1;
else
a[i + 1] = -1;
}
build(1, 1, n);
for (int i = 1; i <= n; i++) {
modify(1, i, n, a[i]);
}

while (m--) {
int op, l, r;
cin >> op >> l >> r;
if (op == 1) {
modify(1, l, n, -a[l]);
modify(1, r, n, -a[r]);
swap(a[l], a[r]);
modify(1, l, n, a[l]);
modify(1, r, n, a[r]);
} else {
int pre;
if (l == 1)
pre = 0;
else
pre = query(1, l - 1, l - 1);
if (query(1, l, r) - pre == 0 && query(1, r, r) - pre == 0) {
puts("Yes");
} else
puts("No");
}
}
}



## Meaning:

Given a positive integer X X X and Y Y Y. In the first quadrant of the two-dimensional coordinate axis, it represents a given length of X X 10. Width is Y Y Rectangle of Y, now let you put three small rectangles into this matrix. The abscissa of the three small rectangles cannot exceed X X 10. Ordinate cannot exceed Y Y Y. The area of three small rectangles shall not be less than A, B and C

## Idea:

Let's first discuss that if you put two small rectangles in the middle of a large rectangle, if it is legal, there must be a line parallel to x x x-axis (or y y The line of y axis) separates the two small rectangles. If it does not exist, it means that the two small rectangles must coincide. Let's take the distance parallel to the x axis. At this time, just put a rectangle first, and then use it y = S x y=\frac{S}{x} y=xS (rounded up), because the meaning of the question requires that the coordinates of the small rectangle must be an integer, and then the remaining length is Y − y Y-y Y − y, see if the rest of the area can fit into a small rectangle.

For placing three small rectangles, if it is legal, there must be one parallel to x x x-axis (or y y A straight line along the y-axis) separates three rectangles, two rectangles on one side and one rectangle on the other. Enumerate first x x x or y y y. Then place a rectangle on one side and use it y = S x y=\frac{S}{x} y=xS (rounded up), the remaining length is Y − y Y-y Y − y, which is the length of the other side of the straight line. For the lower rectangle, use the above method to enumerate.

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

bool solve(ll x, ll y, ll a, ll b) {
for (int i = 0; i < 2; i++) {
ll len = (a + x - 1) / x;
if (len < y && x * (y - len) >= b) {
return true;
}
swap(x, y);
}
return false;
}
bool check(ll x, ll y, ll a, ll b, ll c) {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
ll len = (a + x - 1) / x;
if (len < y && solve(x, y - len, b, c)) {
return true;
}
swap(a, b);
swap(b, c);
}
swap(x, y);
}
return false;
}
int main() {
ll x, y, a, b, c;
cin >> x >> y >> a >> b >> c;
bool t = check(x, y, a, b, c);
if (t)
puts("Yes");
else
puts("No");
return 0;
}


## Meaning:

Present sequence P P P is the permutation of {1,2,3... n}, which is now given m m m conditions, i.e A i A_i Ai: Yes B i B_i In front of Bi ， let you output the arrangement with the smallest dictionary order.

## Idea:

A i A_i Ai ratio B i B_i When Bi ， is small, we regard two numbers as two points in graph theory A i A_i Ai to B i B_i Bi ， connect one edge, then run while sorting topology, maintain the minimum value with the priority queue, and write down the out of queue order

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int h[N], e[N], ne[N], idx;
int du[N];
int n, m;
vector<int> path;
void clear_graph() {
memset(h, -1, sizeof(h));
idx = 0;
memset(du, 0, sizeof(du));
}
void add_edge(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx++; }

int topsort() {
priority_queue<int, vector<int>, greater<int> > q;
for (int i = 1; i <= n; i++) {
if (du[i] == 0) {
q.push(i);
}
}
int cnt = 0;
int rounds = 1;
while (q.size()) {
auto t = q.top();
q.pop();

path.push_back(t);
cnt++;
for (int i = h[t]; ~i; i = ne[i]) {
int j = e[i];
du[j]--;
if (du[j] == 0) {
q.push(j);
}
}
}

if (cnt == n) return 1;
return 0;
}
int main() {
cin >> n >> m;
clear_graph();
for (int i = 0, a, b; i < m; i++) {
cin >> a >> b;
du[b]++;
}

int t = topsort();
if (t == 0)
puts("-1");
else {
for (auto it : path) {
cout << it << " ";
}
}
}


## Meaning:

yes N N N leads. Each lead has a length and burning time. Now ignite the leads on the left and right. Ask how long it will end the burning

## Idea:

First calculate the total time of burning from one end point. At this time, the total time of burning at two points at the same time is half of the total time of one end point. Then burn while running from left to right according to the time until the time is 0 to see which point to stop at

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int N = 1010;
const double eps = 1e-8;

int n, a[N], b[N];

int main() {
cin >> n;
double tot = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i] >> b[i];
tot += (double)a[i] / b[i];
}

tot /= 2;

int i = 1;
double res = 0;

while (tot != 0) {
double temp = (double)a[i] / b[i];
if (tot > temp) {
res += a[i++];
tot -= temp;
} else {
res += b[i] * tot;
break;
}
}

cout << res << endl;
return 0;
}



To be continued
If you have any suggestions or criticisms and additions, please leave a message and point it out. Thank you very much

Posted on Mon, 18 Oct 2021 19:29:02 -0400 by mayus