Loading [MathJax]/extensions/tex2jax.js

P2898:「USACO08JAN」haybale猜测题解

思路

这又是一道抄题解的题目。我们先来简要分析一下触发矛盾的几种情况:

  • 给定两个区间\(A, B\),有\(A \cap B \neq \emptyset \),而\(A_{min} \neq B_{min}\),这种情况是矛盾的。
  • 给定两个区间\(A, B\),有\(A \subset B\),而\(A_{min} \neq B_{min}\),这种情况也是矛盾的。

之后我们就可以用并查集来进行集合操作。而数据范围非常的大,而答案只需要一个最早解,那么我们就可以尝试二分答案。

代码

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// P2898.cpp
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 1000020;
const int INF = 1e9 + 1e8;
int n, q, mem[maxn];
struct RMQ
{
int left, right, exp;
} seq[maxn], tmp[maxn];
bool cmp(RMQ r1, RMQ r2)
{
if (r1.exp == r2.exp)
return r1.left < r2.left;
return r1.exp > r2.exp;
}
int find(int x)
{
return (mem[x] == x) ? mem[x] : mem[x] = find(mem[x]);
}
bool check(int val)
{
int l1 = 0, r1 = INF, l2 = INF, r2 = 0;
// initialize the mem[]
for (int i = 0; i <= n + 1; i++)
mem[i] = i;
for (int i = 1; i <= val; i++)
tmp[i] = seq[i];
sort(tmp + 1, tmp + 1 + val, cmp);
int lval = tmp[1].exp;
l1 = l2 = tmp[1].left, r1 = r2 = tmp[1].right;
for (int i = 2; i <= val; i++)
if (tmp[i].exp != lval)
{
int now = find(l2);
if (find(l1) <= r1)
while (now <= r2)
mem[now] = mem[now + 1], now = find(now + 1);
else
return false;
lval = tmp[i].exp;
l1 = l2 = tmp[i].left;
r1 = r2 = tmp[i].right;
}
else
{
l1 = max(l1, tmp[i].left), r1 = min(r1, tmp[i].right);
l2 = min(l2, tmp[i].left), r2 = max(r2, tmp[i].right);
lval = tmp[i].exp;
if (l1 > r1)
return false;
}
if (find(l1) > r1)
return false;
return true;
}
int main()
{
scanf("%d%d", &n, &q);
for (int i = 1; i <= q; i++)
scanf("%d%d%d", &seq[i].left, &seq[i].right, &seq[i].exp);
int l = 0;
int r = q;
while (l <= r)
{
int mid = ((l + r) >> 1);
if (check(mid))
l = mid + 1;
else
r = mid - 1;
}
if (l > q)
printf("0");
else
printf("%d", l);
return 0;
}
// P2898.cpp #include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int maxn = 1000020; const int INF = 1e9 + 1e8; int n, q, mem[maxn]; struct RMQ { int left, right, exp; } seq[maxn], tmp[maxn]; bool cmp(RMQ r1, RMQ r2) { if (r1.exp == r2.exp) return r1.left < r2.left; return r1.exp > r2.exp; } int find(int x) { return (mem[x] == x) ? mem[x] : mem[x] = find(mem[x]); } bool check(int val) { int l1 = 0, r1 = INF, l2 = INF, r2 = 0; // initialize the mem[] for (int i = 0; i <= n + 1; i++) mem[i] = i; for (int i = 1; i <= val; i++) tmp[i] = seq[i]; sort(tmp + 1, tmp + 1 + val, cmp); int lval = tmp[1].exp; l1 = l2 = tmp[1].left, r1 = r2 = tmp[1].right; for (int i = 2; i <= val; i++) if (tmp[i].exp != lval) { int now = find(l2); if (find(l1) <= r1) while (now <= r2) mem[now] = mem[now + 1], now = find(now + 1); else return false; lval = tmp[i].exp; l1 = l2 = tmp[i].left; r1 = r2 = tmp[i].right; } else { l1 = max(l1, tmp[i].left), r1 = min(r1, tmp[i].right); l2 = min(l2, tmp[i].left), r2 = max(r2, tmp[i].right); lval = tmp[i].exp; if (l1 > r1) return false; } if (find(l1) > r1) return false; return true; } int main() { scanf("%d%d", &n, &q); for (int i = 1; i <= q; i++) scanf("%d%d%d", &seq[i].left, &seq[i].right, &seq[i].exp); int l = 0; int r = q; while (l <= r) { int mid = ((l + r) >> 1); if (check(mid)) l = mid + 1; else r = mid - 1; } if (l > q) printf("0"); else printf("%d", l); return 0; }
// P2898.cpp
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 1000020;
const int INF = 1e9 + 1e8;
int n, q, mem[maxn];
struct RMQ
{
    int left, right, exp;
} seq[maxn], tmp[maxn];

bool cmp(RMQ r1, RMQ r2)
{
    if (r1.exp == r2.exp)
        return r1.left < r2.left;
    return r1.exp > r2.exp;
}

int find(int x)
{
    return (mem[x] == x) ? mem[x] : mem[x] = find(mem[x]);
}

bool check(int val)
{
    int l1 = 0, r1 = INF, l2 = INF, r2 = 0;
    // initialize the mem[]
    for (int i = 0; i <= n + 1; i++)
        mem[i] = i;
    for (int i = 1; i <= val; i++)
        tmp[i] = seq[i];
    sort(tmp + 1, tmp + 1 + val, cmp);
    int lval = tmp[1].exp;
    l1 = l2 = tmp[1].left, r1 = r2 = tmp[1].right;
    for (int i = 2; i <= val; i++)
        if (tmp[i].exp != lval)
        {
            int now = find(l2);
            if (find(l1) <= r1)
                while (now <= r2)
                    mem[now] = mem[now + 1], now = find(now + 1);
            else
                return false;
            lval = tmp[i].exp;
            l1 = l2 = tmp[i].left;
            r1 = r2 = tmp[i].right;
        }
        else
        {
            l1 = max(l1, tmp[i].left), r1 = min(r1, tmp[i].right);
            l2 = min(l2, tmp[i].left), r2 = max(r2, tmp[i].right);
            lval = tmp[i].exp;
            if (l1 > r1)
                return false;
        }
    if (find(l1) > r1)
        return false;
    return true;
}

int main()
{
    scanf("%d%d", &n, &q);
    for (int i = 1; i <= q; i++)
        scanf("%d%d%d", &seq[i].left, &seq[i].right, &seq[i].exp);
    int l = 0;
    int r = q;
    while (l <= r)
    {
        int mid = ((l + r) >> 1);
        if (check(mid))
            l = mid + 1;
        else
            r = mid - 1;
    }
    if (l > q)
        printf("0");
    else
        printf("%d", l);
    return 0;
}

Leave a Reply

Your email address will not be published. Required fields are marked *