Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define _CRT_SECURE_NO_WARNINGS
- #include <iostream>
- #include <vector>
- #include <algorithm>
- #include <cmath>
- #include <iomanip>
- #include <fstream>
- #include <string>
- #include <set>
- #include <deque>
- #include <queue>
- #include <map>
- #include <bitset>
- #include <random>
- #include <cassert>
- #include <unordered_map>
- #include <unordered_set>
- #include <math.h>
- #include <chrono>
- #include <ctime>
- using namespace std;
- using namespace chrono;
- #define all(a) a.begin(), a.end()
- #define endl "\n"
- typedef long long ll;
- typedef long double ld;
- ll timer = 0;
- mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
- double gen_rand() {
- ll x = rnd() + 1;
- ll y = rnd() + 1;
- x %= y;
- return x / (double)y;
- }
- ll stop = 1e4;
- ll ans = 1e18;
- void break_point(ll& timer) {
- if (timer % stop == 0) {
- if (clock() / (double)CLOCKS_PER_SEC >= 2.8) {
- cout << ans << endl;
- exit(0);
- }
- }
- }
- vector<vector<vector<ll>>> mas_of_tree;
- ll query(ll v, ll tl, ll tr, ll l, ll r, ll x, ll ind_of_tree) {
- timer++;
- break_point(timer);
- if (tr<l || r<tl) {
- return 0;
- }
- if (tl>=l && tr<= r) {
- if (!mas_of_tree[ind_of_tree][v].empty()) {
- ll pos = lower_bound(all(mas_of_tree[ind_of_tree][v]), x) - mas_of_tree[ind_of_tree][v].begin();
- ll pos2 = upper_bound(all(mas_of_tree[ind_of_tree][v]), x) - mas_of_tree[ind_of_tree][v].begin();
- return pos2 - pos;
- }
- else {
- return 0;
- }
- }
- ll tm = (tl + tr) / 2;
- return query(v * 2, tl, tm, l, r, x, ind_of_tree) + query(v * 2 + 1, tm + 1, tr, l, r, x, ind_of_tree);
- }
- struct st {
- struct node {
- ll val;
- ll ind;
- };
- vector<node> tree;
- void seg(ll n, vector<ll>& a) {
- timer++;
- tree.resize(4 * n + 13);
- build(1, 0, n, a);
- }
- void smerge(ll v, ll l, ll r) {
- timer++;
- break_point(timer);
- if (l + 1 == r) {
- return;
- }
- if (tree[2 * v].val < tree[2 * v + 1].val) {
- tree[v].val = tree[2 * v].val;
- tree[v].ind = tree[2 * v].ind;
- }
- else {
- tree[v].val = tree[2 * v + 1].val;
- tree[v].ind = tree[2 * v + 1].ind;
- }
- }
- void build(ll v, ll l, ll r, vector<ll>& a) {
- timer++;
- break_point(timer);
- if (l + 1 == r) {
- tree[v].val = a[l];
- tree[v].ind = l;
- return;
- }
- ll m = (l + r) / 2;
- build(2 * v, l, m, a);
- build(2 * v + 1, m, r, a);
- smerge(v, l, r);
- }
- ll getI(ll v, ll l, ll r, ll lq, ll rq, ll add) {
- timer++;
- break_point(timer);
- if (lq >= r || rq <= l) {
- return -1;
- }
- if (l + 1 == r) {
- return (tree[v].val + add < 0 ? tree[v].ind : -1);
- }
- ll m = (l + r) / 2;
- ll ans = -1;
- if (tree[2 * v].val + add < 0 && lq <= m) {
- ans = getI(2 * v, l, m, lq, rq, add);
- }
- if (tree[2 * v + 1].val + add < 0 && lq < r && ans == -1) {
- ans = getI(2 * v + 1, m, r, lq, rq, 0);
- }
- return ans;
- }
- };
- vector<st> t;
- void build(vector<ll>& pref_sum, ll v, ll tl, ll tr, ll ind_of_tree) {
- break_point(timer);
- if (tl == tr) {
- mas_of_tree[ind_of_tree][v] =
- vector<ll>(1, pref_sum[tl]);
- return;
- }
- ll mid = (tl + tr) / 2;
- build(pref_sum, v * 2, tl, mid, ind_of_tree);
- build(pref_sum, v * 2 + 1, mid + 1, tr, ind_of_tree);
- merge(all(mas_of_tree[ind_of_tree][v * 2]), all(mas_of_tree[ind_of_tree][v * 2 + 1]), back_inserter(mas_of_tree[ind_of_tree][v]));
- timer++;
- }
- ll get(vector<vector<ll>>& cur,vector<ll> &p) {
- ll now = 0;
- ll res = 0;
- bool brek = false;
- for (ll i = 0; i < (ll)cur.size(); i++) {
- timer++;
- break_point(timer);
- ll pos = t[p[i]].getI(1, 0, (ll)cur[i].size(), 0, (ll)cur[i].size(), now);
- if (pos != -1) {
- brek = true;
- }
- else {
- pos = (ll)cur[i].size() - 1;
- }
- res += query(1, 0, (ll)cur[i].size() - 1, 0, pos, -now, p[i]);
- if (brek) {
- break;
- }
- now += cur[i][cur[i].size() - 1];
- }
- return res;
- }
- signed main() {
- #ifdef _DEBUG
- freopen("input.txt", "r", stdin);
- freopen("output.txt", "w", stdout);
- #endif
- ios_base::sync_with_stdio(false);
- cin.tie(nullptr);
- cout.tie(nullptr);
- srand(time(NULL));
- ll n;
- cin >> n;
- vector<vector<ll>> a(n);
- mas_of_tree.resize(n);
- t.resize(n);
- for (ll i = 0; i < n; i++) {
- string s;
- cin >> s;
- ll log = 1;
- mas_of_tree[i].resize((ll)s.size() * 4);
- a[i].resize((ll)s.size());
- ll cur = 0;
- for (ll j = 0; j < (ll)a[i].size(); j++) {
- timer++;
- break_point(timer);
- if (s[j] == '(')cur++;
- else cur--;
- a[i][j] = cur;
- }
- build(a[i], 1, 0, (ll)a[i].size() - 1, i);
- t[i].seg((ll)a[i].size(), a[i]);
- timer++;
- }
- double temp = 1000;
- double t0 = 1000;
- vector<ll> main_p(n);
- for (ll i = 0; i < n; i++) {
- main_p[i] = i;
- }
- ll last_res = get(a,main_p);
- ans = last_res;
- ld eps = 1.0 / (double)n;
- while (1) {
- temp = 1000.0;
- while (temp > eps) {
- timer++;
- break_point(timer);
- vector<vector<ll>> sub = a;
- vector<ll> prev_p = main_p;
- for (ll i = 0; i < n * temp / t0; i++) {
- timer++;
- break_point(timer);
- ll k1 = rnd() % n;
- ll k2 = rnd() % n;
- swap(sub[k1], sub[k2]);
- swap(prev_p[k1], prev_p[k2]);
- }
- ll now_res = get(sub, prev_p);
- if (now_res > ans) {
- ans = now_res;
- }
- timer++;
- break_point(timer);
- double go = exp((now_res - last_res) / temp);
- if (now_res > last_res || gen_rand() <= go) {
- a = sub;
- main_p = prev_p;
- last_res = now_res;
- }
- temp *= 0.995;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement