目录
G. Hard Brackets Problem
I. Barkley II
K. Randias permutation task
M. Flipping Cards
补题中
注意到,如果答案存在的话,输出串一定是一个合法输入串。可以通过模拟或者后缀和来判断无解。时间复杂度 Θ(n)。
signed main()
{
ios_base::sync_with_stdio(0); cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--)
{
string s;
cin >> s;
int cnt = 0;
for (int i = 0; i < s.size(); i++) {
if (s[i] == '(') cnt++;
else {
if (cnt) cnt--;
}
}
if (cnt) {
cout << "impossible\n";
}
else {
cout << s << "\n";
}
}
}
首先先看全选的值是多少,将他赋给最终结果
然后,假设这个数组中某一个数是MEX,这时候你可以根据这个MEX对区间进行划分
比如数组是
1 2 3 4 5 6 7 8 9 10 11
4 5 6 1 7 8 9 4 5 1 5
假设5是MEX可以划分成(1,1),(3,8),(10,10)
假设7是MEX(1,4),(6,11)
。。。
然后结果就是用这个区间不同的数减去MEX值,取最大值
还得对所以数进行离散化
求区间不同的数之间看这个吧:区间内不同数的个数_区间有多少不同的数-CSDN博客
unordered_mapmp;
struct Tree
{
int l, r;
int val;
}tr[4 * N];
void build(int p, int l, int r)
{
tr[p].l = l, tr[p].r = r, tr[p].val = 0;
if (l == r) {
return;
}
int mid = l + r >> 1;
build(p * 2, l, mid); build(p * 2 + 1, mid + 1, r);
}
void change(int p, int x, int val) {
if (tr[p].l == tr[p].r) {
tr[p].val = val;
return;
}
int mid = tr[p].l + tr[p].r >> 1;
if (x <= mid) change(p * 2, x, val);
else change(p * 2 + 1, x, val);
tr[p].val = tr[p * 2].val + tr[p * 2 + 1].val;
}
vectorq[N];
struct node {
int l, r, val;
};
bool cmp(node& k1, node& k2) {
return k1.r < k2.r;
}
int st[N];
int ask(int p, int l, int r)
{
if (l <= tr[p].l && tr[p].r <= r) {
return tr[p].val;
}
int mid = tr[p].l + tr[p].r >> 1;
int sum = 0;
if (l <= mid) sum += ask(p * 2, l, r);
if (r > mid) sum += ask(p * 2 + 1, l, r);
return sum;
}
signed main()
{
ios_base::sync_with_stdio(0); cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--)
{
int n, m;
cin >> n >> m;
build(1, 1, n);
vectora(n + 1);
vectorp;
p.push_back(0);
for (int i = 1; i <= n+1; i++) {
st[i] = 0;
}
for (int i = 1; i <= n; i++) {
cin >> a[i];
if (a[i] <= n) st[a[i]] = 1;
p.push_back(a[i]);
}
int wc = 0;
for (int i = 1; i <= n+1; i++) {
if (st[i] == 0) {
wc = i;
break;
}
}
sort(p.begin(), p.end());
p.erase(unique(p.begin(), p.end()), p.end());//离散化
for (int i = 1; i < p.size(); i++) {
q[i].clear(); st[i] = 0;
q[i].push_back(0);
mp[p[i]] = i;
}
vectornod;
for (int i = 1; i <= n; i++) {
nod.push_back({ q[mp[a[i]]].back()+1,i-1,a[i] });
q[mp[a[i]]].push_back(i);
}
for (int i = 1; i < p.size(); i++) {
nod.push_back({ q[i].back()+1,n,p[i] });
q[i].push_back(n + 1);
}
sort(nod.begin(), nod.end(), cmp);
int pos = 0;
int maxx = (p.size() - 1 - wc);;
for (int i = 0; i < nod.size(); i++) {
if (nod[i].r == 0 || nod[i].l > nod[i].r) continue;
while (pos < nod[i].r) {
pos++;
if (st[mp[a[pos]]]) {
change(1, st[mp[a[pos]]], 0);
}
change(1, i, 1);
st[mp[a[pos]]] = i;
}
maxx = max(maxx, ask(1, nod[i].l, nod[i].r) - nod[i].val);
}
cout << maxx << "\n";
}
}
注意到答案不超过 min{2m, n!} ≤ 362880,所以任何复杂度是 O(ans) 级别的爆搜都是正确的。具体来说,令 fi 表示前 i 个排列能复合出的排列的集合,每次枚举下一个排列选不选即可。时间复杂度 Θ(nm · min(2m, n!) · log min(2m, n!))。
#define int long long//__int128 2^127-1(GCC)
#define PII pair
const int inf = 0x3f3f3f3f3f3f3f3f, N = 180 + 5, mod = 1e9 + 7;
map, int>mp;
signed main()
{
ios_base::sync_with_stdio(0); cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
vector>a(m+1, vector(n+1));
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
cin >> a[i][j];
}
}
vectorres(n + 1);
for (int i = 1; i <= m; i++) {
map, int>tmp;
tmp = mp;
tmp[a[i]] = 1;
for (auto w : mp) {
vectorp = w.first;
for (int j = 1; j <= n; j++) {
res[j] = p[a[i][j]];
}
tmp[res]=1;
}
mp = tmp;
}
cout << mp.size() << '\n';
}
二分答案 w,那么就是要求 [bi ≥ w] − [ai ≥ w] 的最大子段和。时间复杂度 Θ(n log a)。
const int inf = 0x3f3f3f3f3f3f3f3f, N = 3e5 + 5, mod = 1e9 + 7;
int a[N], b[N];
int n;
int st[N], pre[N];
bool check(int x)
{
for (int i = 1; i <= n; i++) {
if (a[i] < x && b[i] >= x) {
st[i] = 1;
}
else if (a[i] >= x && b[i] < x) {
st[i] = -1;
}
else {
st[i] = 0;
}
pre[i] = pre[i - 1] + st[i];
}
int l = 0, r = 0;
int minn = 0, ll = 0;
int maxx = 0, rr = 0;
for (int i = 1; i <= n; i++) {
if (pre[i] - pre[ll] > maxx) {
maxx = pre[i] - pre[ll];
l = ll + 1, r = i;
}
if (pre[i] < minn) {
minn = pre[i];
ll = i;
}
}
int g = 0, s = 0;
for (int i = 1; i <= n; i++) {
if (i >= l && i <= r) {
if (b[i] >= x) g++;
else s++;
}
else {
if (a[i] >= x) g++;
else s++;
}
}
if (g - s >= 0) return 1;
else return 0;
}
signed main()
{
ios_base::sync_with_stdio(0); cin.tie(0), cout.tie(0);
//int n;
cin >> n;
//vectora(n + 1), b(n + 1);
for (int i = 1; i <= n; i++) {
cin >> a[i] >> b[i];
}
int l = 1, r = 1e9+10;
while (l < r) {
int mid = l + r >> 1;
if (check(mid)) l = mid+1;
else r = mid ;
}
if (!check(l)) l--;
cout << l << '\n';
}