Loading [MathJax]/extensions/tex2jax.js

「USACO 2018.01 Platinum」解题报告

A – Lifeguards

先可以想到把所有的包含的区间给去掉,然后来关注如何进行 DP。我们可以考虑设置 \(dp[i][j]\) 为前 \(i\) 个区间里删掉了 \(j\) 个区间的最优答案。正常我们做「选择 \(j\) 个区间」的问题会比较简单,然而 \(k \leq 200\) 就很麻烦。

我们如何来进行转移呢?首先,我们转移时可以考虑从 \(dp[x][y]\) 来进行转移而不只是经典的 \(dp[i – 1][j – 1] \text{或} dp[i – 1][j]\)。如果使用经典转移,就很难去分开维护重叠信息。转移有个条件 \(i – j – 1 = x – y\),比较显然,可以使用单调队列来进行维护。需要注意的是,我们要同时维护重叠、非重叠的信息。重叠的信息可以考虑直接在维护时减去一个右边界;而非重叠放在队列的 global array 里就可以了。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// LOJ2385.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e5 + 200, MAX_K = 110;
typedef pair<int, int> pii;
int n, limit, dp[MAX_N][MAX_K], max_prod[MAX_N];
deque<pii> dq[MAX_N];
struct segment
{
int l, r;
bool operator<(const segment &rhs) const { return l < rhs.l || (l == rhs.l && r > rhs.r); }
} segs[MAX_N];
inline char gc()
{
static char buf[1000000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
}
int read()
{
int x = 0, f = 1;
char ch = gc();
while (!isdigit(ch))
{
if (ch == '-')
f = -1;
ch = gc();
}
while (isdigit(ch))
x = (x << 3) + (x << 1) + ch - '0', ch = gc();
return f * x;
}
int main()
{
// freopen("2.in", "r", stdin);
n = read(), limit = read();
for (int i = 1; i <= n; i++)
segs[i].l = read(), segs[i].r = read();
sort(segs + 1, segs + 1 + n);
int tot = 1;
for (int i = 2; i <= n; i++)
if (segs[i].r > segs[tot].r)
segs[++tot] = segs[i];
limit -= (n - tot), n = tot, limit = max(0, limit);
for (int i = 1; i <= n; i++)
{
for (int j = 0; j < min(limit + 1, i); j++)
{
int curt = i - j - 1;
while (!dq[curt].empty() && segs[dq[curt].front().second].r < segs[i].l)
// not overlap;
max_prod[curt] = max(max_prod[curt], segs[dq[curt].front().second].r + dq[curt].front().first), dq[curt].pop_front();
dp[i][j] = max(dp[i][j], max_prod[curt] + segs[i].r - segs[i].l);
if (!dq[curt].empty())
dp[i][j] = max(dp[i][j], segs[i].r + dq[curt].front().first);
int val = dp[i][j] - segs[i].r;
curt++;
while (!dq[curt].empty() && dq[curt].back().first < val)
dq[curt].pop_back();
dq[curt].push_back(make_pair(val, i));
}
}
int ans = 0;
for (int i = 1; i <= n; i++)
for (int j = 0; j < min(limit + 1, i); j++)
if (i - j == n - limit)
ans = max(ans, dp[i][j]);
printf("%d\n", ans);
return 0;
}
// LOJ2385.cpp #include <bits/stdc++.h> using namespace std; const int MAX_N = 1e5 + 200, MAX_K = 110; typedef pair<int, int> pii; int n, limit, dp[MAX_N][MAX_K], max_prod[MAX_N]; deque<pii> dq[MAX_N]; struct segment { int l, r; bool operator<(const segment &rhs) const { return l < rhs.l || (l == rhs.l && r > rhs.r); } } segs[MAX_N]; inline char gc() { static char buf[1000000], *p1 = buf, *p2 = buf; return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++; } int read() { int x = 0, f = 1; char ch = gc(); while (!isdigit(ch)) { if (ch == '-') f = -1; ch = gc(); } while (isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = gc(); return f * x; } int main() { // freopen("2.in", "r", stdin); n = read(), limit = read(); for (int i = 1; i <= n; i++) segs[i].l = read(), segs[i].r = read(); sort(segs + 1, segs + 1 + n); int tot = 1; for (int i = 2; i <= n; i++) if (segs[i].r > segs[tot].r) segs[++tot] = segs[i]; limit -= (n - tot), n = tot, limit = max(0, limit); for (int i = 1; i <= n; i++) { for (int j = 0; j < min(limit + 1, i); j++) { int curt = i - j - 1; while (!dq[curt].empty() && segs[dq[curt].front().second].r < segs[i].l) // not overlap; max_prod[curt] = max(max_prod[curt], segs[dq[curt].front().second].r + dq[curt].front().first), dq[curt].pop_front(); dp[i][j] = max(dp[i][j], max_prod[curt] + segs[i].r - segs[i].l); if (!dq[curt].empty()) dp[i][j] = max(dp[i][j], segs[i].r + dq[curt].front().first); int val = dp[i][j] - segs[i].r; curt++; while (!dq[curt].empty() && dq[curt].back().first < val) dq[curt].pop_back(); dq[curt].push_back(make_pair(val, i)); } } int ans = 0; for (int i = 1; i <= n; i++) for (int j = 0; j < min(limit + 1, i); j++) if (i - j == n - limit) ans = max(ans, dp[i][j]); printf("%d\n", ans); return 0; }
// LOJ2385.cpp
#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 1e5 + 200, MAX_K = 110;

typedef pair<int, int> pii;

int n, limit, dp[MAX_N][MAX_K], max_prod[MAX_N];
deque<pii> dq[MAX_N];

struct segment
{
    int l, r;
    bool operator<(const segment &rhs) const { return l < rhs.l || (l == rhs.l && r > rhs.r); }
} segs[MAX_N];

inline char gc()
{
    static char buf[1000000], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
}

int read()
{
    int x = 0, f = 1;
    char ch = gc();
    while (!isdigit(ch))
    {
        if (ch == '-')
            f = -1;
        ch = gc();
    }
    while (isdigit(ch))
        x = (x << 3) + (x << 1) + ch - '0', ch = gc();
    return f * x;
}

int main()
{
    // freopen("2.in", "r", stdin);
    n = read(), limit = read();
    for (int i = 1; i <= n; i++)
        segs[i].l = read(), segs[i].r = read();
    sort(segs + 1, segs + 1 + n);
    int tot = 1;
    for (int i = 2; i <= n; i++)
        if (segs[i].r > segs[tot].r)
            segs[++tot] = segs[i];
    limit -= (n - tot), n = tot, limit = max(0, limit);
    for (int i = 1; i <= n; i++)
    {
        for (int j = 0; j < min(limit + 1, i); j++)
        {
            int curt = i - j - 1;
            while (!dq[curt].empty() && segs[dq[curt].front().second].r < segs[i].l)
                // not overlap;
                max_prod[curt] = max(max_prod[curt], segs[dq[curt].front().second].r + dq[curt].front().first), dq[curt].pop_front();
            dp[i][j] = max(dp[i][j], max_prod[curt] + segs[i].r - segs[i].l);
            if (!dq[curt].empty())
                dp[i][j] = max(dp[i][j], segs[i].r + dq[curt].front().first);
            int val = dp[i][j] - segs[i].r;
            curt++;
            while (!dq[curt].empty() && dq[curt].back().first < val)
                dq[curt].pop_back();
            dq[curt].push_back(make_pair(val, i));
        }
    }
    int ans = 0;
    for (int i = 1; i <= n; i++)
        for (int j = 0; j < min(limit + 1, i); j++)
            if (i - j == n - limit)
                ans = max(ans, dp[i][j]);
    printf("%d\n", ans);
    return 0;
}

B – Cow at Large

这题就只想到了 \(\Theta(n^2)\) 的中点标记的方法,看题解发现竟然还能用点分治来搞,发现是个板子

考虑当前根 \(u\),对于 \(i\) 最近的叶子结点的距离为 \(g_i\),则中点满足:

\[ g[i] \leq dep_i \text{and} dep_fa < g_i \]

然后有一个套路,就是 \(\sum d_i = 2S – 1, 1 = \sum d_i – 2\),然后我们用艾弗森括号套上去即可。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// LOJ2386.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e5 + 200;
int n, head[MAX_N], current, g[MAX_N], dep[MAX_N], deg[MAX_N], ans[MAX_N], siz[MAX_N], nodes[MAX_N << 1];
bool tag[MAX_N];
struct edge
{
int to, nxt;
} edges[MAX_N << 1];
inline char gc()
{
static char buf[1000000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
}
int read()
{
int x = 0, f = 1;
char ch = gc();
while (!isdigit(ch))
{
if (ch == '-')
f = -1;
ch = gc();
}
while (isdigit(ch))
x = (x << 3) + (x << 1) + ch - '0', ch = gc();
return f * x;
}
void addpath(int src, int dst)
{
edges[current].to = dst, edges[current].nxt = head[src];
head[src] = current++;
}
void dfs(int u, int fa)
{
if (deg[u] == 1)
g[u] = 0;
for (int i = head[u]; i != -1; i = edges[i].nxt)
if (edges[i].to != fa)
dfs(edges[i].to, u), g[u] = min(g[u], g[edges[i].to] + 1);
}
void overlap(int u, int fa)
{
for (int i = head[u]; i != -1; i = edges[i].nxt)
if (edges[i].to != fa)
g[edges[i].to] = min(g[edges[i].to], g[u] + 1), overlap(edges[i].to, u);
}
int root, root_val;
void findRoot(int u, int fa, int capacity)
{
siz[u] = 1;
int max_com = 0;
for (int i = head[u]; i != -1; i = edges[i].nxt)
if (edges[i].to != fa && !tag[edges[i].to])
findRoot(edges[i].to, u, capacity), max_com = max(max_com, siz[edges[i].to]), siz[u] += siz[edges[i].to];
if (max(max_com, capacity - siz[u]) < root_val)
root_val = max(max_com, capacity - siz[u]), root = u;
}
int findRoot(int entry, int capacity) { return root = 0, root_val = 0x7fffffff, findRoot(entry, 0, capacity), root; }
inline int lowbit(int x) { return x & (-x); }
void update(int x, int d)
{
x += MAX_N;
for (; x <= MAX_N << 1; x += lowbit(x))
nodes[x] += d;
}
int query(int x, int ret = 0)
{
x += MAX_N;
for (; x; x -= lowbit(x))
ret += nodes[x];
return ret;
}
void collect(int u, int fa, int dep)
{
ans[u] += query(dep);
for (int i = head[u]; i != -1; i = edges[i].nxt)
if (edges[i].to != fa && !tag[edges[i].to])
collect(edges[i].to, u, dep + 1);
}
void confirm(int u, int fa, int dep)
{
update(g[u] - dep, 2 - deg[u]);
for (int i = head[u]; i != -1; i = edges[i].nxt)
if (edges[i].to != fa && !tag[edges[i].to])
confirm(edges[i].to, u, dep + 1);
}
void clear(int u, int fa, int dep)
{
update(g[u] - dep, deg[u] - 2), siz[u] = 1;
for (int i = head[u]; i != -1; i = edges[i].nxt)
if (edges[i].to != fa && !tag[edges[i].to])
clear(edges[i].to, u, dep + 1), siz[u] += siz[edges[i].to];
}
int cnt;
void solve(int u, int capacity)
{
tag[u] = true; //, printf("TAGGED Another One: %d\n", cnt), cnt++;
stack<int> sons;
for (int i = head[u]; i != -1; i = edges[i].nxt)
if (!tag[edges[i].to])
collect(edges[i].to, u, 1), confirm(edges[i].to, u, 1), sons.push(edges[i].to);
for (int i = head[u]; i != -1; i = edges[i].nxt)
if (!tag[edges[i].to])
clear(edges[i].to, u, 1);
update(g[u], 2 - deg[u]);
while (!sons.empty())
{
int v = sons.top();
collect(v, u, 1), confirm(v, u, 1), sons.pop();
}
ans[u] += query(0), update(g[u], deg[u] - 2);
for (int i = head[u]; i != -1; i = edges[i].nxt)
if (!tag[edges[i].to])
clear(edges[i].to, u, 1);
for (int i = head[u]; i != -1; i = edges[i].nxt)
if (!tag[edges[i].to])
solve(findRoot(edges[i].to, siz[edges[i].to]), siz[edges[i].to]);
}
int main()
{
/*
freopen("2.in", "r", stdin);
freopen("2.out", "w", stdout);
*/
memset(head, -1, sizeof(head)), memset(g, 0x3f, sizeof(g));
n = read();
for (int i = 1, u, v; i <= n - 1; i++)
u = read(), v = read(), addpath(u, v), addpath(v, u), deg[u]++, deg[v]++;
dfs(1, 0), overlap(1, 0), solve(findRoot(1, n), n);
for (int i = 1; i <= n; i++)
if (deg[i] == 1)
puts("1");
else
printf("%d\n", ans[i]);
return 0;
}
// LOJ2386.cpp #include <bits/stdc++.h> using namespace std; const int MAX_N = 1e5 + 200; int n, head[MAX_N], current, g[MAX_N], dep[MAX_N], deg[MAX_N], ans[MAX_N], siz[MAX_N], nodes[MAX_N << 1]; bool tag[MAX_N]; struct edge { int to, nxt; } edges[MAX_N << 1]; inline char gc() { static char buf[1000000], *p1 = buf, *p2 = buf; return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++; } int read() { int x = 0, f = 1; char ch = gc(); while (!isdigit(ch)) { if (ch == '-') f = -1; ch = gc(); } while (isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = gc(); return f * x; } void addpath(int src, int dst) { edges[current].to = dst, edges[current].nxt = head[src]; head[src] = current++; } void dfs(int u, int fa) { if (deg[u] == 1) g[u] = 0; for (int i = head[u]; i != -1; i = edges[i].nxt) if (edges[i].to != fa) dfs(edges[i].to, u), g[u] = min(g[u], g[edges[i].to] + 1); } void overlap(int u, int fa) { for (int i = head[u]; i != -1; i = edges[i].nxt) if (edges[i].to != fa) g[edges[i].to] = min(g[edges[i].to], g[u] + 1), overlap(edges[i].to, u); } int root, root_val; void findRoot(int u, int fa, int capacity) { siz[u] = 1; int max_com = 0; for (int i = head[u]; i != -1; i = edges[i].nxt) if (edges[i].to != fa && !tag[edges[i].to]) findRoot(edges[i].to, u, capacity), max_com = max(max_com, siz[edges[i].to]), siz[u] += siz[edges[i].to]; if (max(max_com, capacity - siz[u]) < root_val) root_val = max(max_com, capacity - siz[u]), root = u; } int findRoot(int entry, int capacity) { return root = 0, root_val = 0x7fffffff, findRoot(entry, 0, capacity), root; } inline int lowbit(int x) { return x & (-x); } void update(int x, int d) { x += MAX_N; for (; x <= MAX_N << 1; x += lowbit(x)) nodes[x] += d; } int query(int x, int ret = 0) { x += MAX_N; for (; x; x -= lowbit(x)) ret += nodes[x]; return ret; } void collect(int u, int fa, int dep) { ans[u] += query(dep); for (int i = head[u]; i != -1; i = edges[i].nxt) if (edges[i].to != fa && !tag[edges[i].to]) collect(edges[i].to, u, dep + 1); } void confirm(int u, int fa, int dep) { update(g[u] - dep, 2 - deg[u]); for (int i = head[u]; i != -1; i = edges[i].nxt) if (edges[i].to != fa && !tag[edges[i].to]) confirm(edges[i].to, u, dep + 1); } void clear(int u, int fa, int dep) { update(g[u] - dep, deg[u] - 2), siz[u] = 1; for (int i = head[u]; i != -1; i = edges[i].nxt) if (edges[i].to != fa && !tag[edges[i].to]) clear(edges[i].to, u, dep + 1), siz[u] += siz[edges[i].to]; } int cnt; void solve(int u, int capacity) { tag[u] = true; //, printf("TAGGED Another One: %d\n", cnt), cnt++; stack<int> sons; for (int i = head[u]; i != -1; i = edges[i].nxt) if (!tag[edges[i].to]) collect(edges[i].to, u, 1), confirm(edges[i].to, u, 1), sons.push(edges[i].to); for (int i = head[u]; i != -1; i = edges[i].nxt) if (!tag[edges[i].to]) clear(edges[i].to, u, 1); update(g[u], 2 - deg[u]); while (!sons.empty()) { int v = sons.top(); collect(v, u, 1), confirm(v, u, 1), sons.pop(); } ans[u] += query(0), update(g[u], deg[u] - 2); for (int i = head[u]; i != -1; i = edges[i].nxt) if (!tag[edges[i].to]) clear(edges[i].to, u, 1); for (int i = head[u]; i != -1; i = edges[i].nxt) if (!tag[edges[i].to]) solve(findRoot(edges[i].to, siz[edges[i].to]), siz[edges[i].to]); } int main() { /* freopen("2.in", "r", stdin); freopen("2.out", "w", stdout); */ memset(head, -1, sizeof(head)), memset(g, 0x3f, sizeof(g)); n = read(); for (int i = 1, u, v; i <= n - 1; i++) u = read(), v = read(), addpath(u, v), addpath(v, u), deg[u]++, deg[v]++; dfs(1, 0), overlap(1, 0), solve(findRoot(1, n), n); for (int i = 1; i <= n; i++) if (deg[i] == 1) puts("1"); else printf("%d\n", ans[i]); return 0; }
// LOJ2386.cpp
#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 1e5 + 200;

int n, head[MAX_N], current, g[MAX_N], dep[MAX_N], deg[MAX_N], ans[MAX_N], siz[MAX_N], nodes[MAX_N << 1];
bool tag[MAX_N];

struct edge
{
    int to, nxt;
} edges[MAX_N << 1];

inline char gc()
{
    static char buf[1000000], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
}

int read()
{
    int x = 0, f = 1;
    char ch = gc();
    while (!isdigit(ch))
    {
        if (ch == '-')
            f = -1;
        ch = gc();
    }
    while (isdigit(ch))
        x = (x << 3) + (x << 1) + ch - '0', ch = gc();
    return f * x;
}

void addpath(int src, int dst)
{
    edges[current].to = dst, edges[current].nxt = head[src];
    head[src] = current++;
}

void dfs(int u, int fa)
{
    if (deg[u] == 1)
        g[u] = 0;
    for (int i = head[u]; i != -1; i = edges[i].nxt)
        if (edges[i].to != fa)
            dfs(edges[i].to, u), g[u] = min(g[u], g[edges[i].to] + 1);
}

void overlap(int u, int fa)
{
    for (int i = head[u]; i != -1; i = edges[i].nxt)
        if (edges[i].to != fa)
            g[edges[i].to] = min(g[edges[i].to], g[u] + 1), overlap(edges[i].to, u);
}

int root, root_val;

void findRoot(int u, int fa, int capacity)
{
    siz[u] = 1;
    int max_com = 0;
    for (int i = head[u]; i != -1; i = edges[i].nxt)
        if (edges[i].to != fa && !tag[edges[i].to])
            findRoot(edges[i].to, u, capacity), max_com = max(max_com, siz[edges[i].to]), siz[u] += siz[edges[i].to];
    if (max(max_com, capacity - siz[u]) < root_val)
        root_val = max(max_com, capacity - siz[u]), root = u;
}

int findRoot(int entry, int capacity) { return root = 0, root_val = 0x7fffffff, findRoot(entry, 0, capacity), root; }

inline int lowbit(int x) { return x & (-x); }

void update(int x, int d)
{
    x += MAX_N;
    for (; x <= MAX_N << 1; x += lowbit(x))
        nodes[x] += d;
}

int query(int x, int ret = 0)
{
    x += MAX_N;
    for (; x; x -= lowbit(x))
        ret += nodes[x];
    return ret;
}

void collect(int u, int fa, int dep)
{
    ans[u] += query(dep);
    for (int i = head[u]; i != -1; i = edges[i].nxt)
        if (edges[i].to != fa && !tag[edges[i].to])
            collect(edges[i].to, u, dep + 1);
}

void confirm(int u, int fa, int dep)
{
    update(g[u] - dep, 2 - deg[u]);
    for (int i = head[u]; i != -1; i = edges[i].nxt)
        if (edges[i].to != fa && !tag[edges[i].to])
            confirm(edges[i].to, u, dep + 1);
}

void clear(int u, int fa, int dep)
{
    update(g[u] - dep, deg[u] - 2), siz[u] = 1;
    for (int i = head[u]; i != -1; i = edges[i].nxt)
        if (edges[i].to != fa && !tag[edges[i].to])
            clear(edges[i].to, u, dep + 1), siz[u] += siz[edges[i].to];
}

int cnt;

void solve(int u, int capacity)
{
    tag[u] = true; //, printf("TAGGED Another One: %d\n", cnt), cnt++;
    stack<int> sons;
    for (int i = head[u]; i != -1; i = edges[i].nxt)
        if (!tag[edges[i].to])
            collect(edges[i].to, u, 1), confirm(edges[i].to, u, 1), sons.push(edges[i].to);
    for (int i = head[u]; i != -1; i = edges[i].nxt)
        if (!tag[edges[i].to])
            clear(edges[i].to, u, 1);
    update(g[u], 2 - deg[u]);
    while (!sons.empty())
    {
        int v = sons.top();
        collect(v, u, 1), confirm(v, u, 1), sons.pop();
    }
    ans[u] += query(0), update(g[u], deg[u] - 2);
    for (int i = head[u]; i != -1; i = edges[i].nxt)
        if (!tag[edges[i].to])
            clear(edges[i].to, u, 1);
    for (int i = head[u]; i != -1; i = edges[i].nxt)
        if (!tag[edges[i].to])
            solve(findRoot(edges[i].to, siz[edges[i].to]), siz[edges[i].to]);
}

int main()
{
    /*
    freopen("2.in", "r", stdin);
    freopen("2.out", "w", stdout);
    */
    memset(head, -1, sizeof(head)), memset(g, 0x3f, sizeof(g));
    n = read();
    for (int i = 1, u, v; i <= n - 1; i++)
        u = read(), v = read(), addpath(u, v), addpath(v, u), deg[u]++, deg[v]++;
    dfs(1, 0), overlap(1, 0), solve(findRoot(1, n), n);
    for (int i = 1; i <= n; i++)
        if (deg[i] == 1)
            puts("1");
        else
            printf("%d\n", ans[i]);
    return 0;
}

C – Sprinklers

画一下图,发现区域有点像一个反比例函数的图像,我们维护一下边界得到:

\[ \sum_{i = 1}^n \sum_{j = lft_i}^{rig_i} (c_j – i)(j – lft_i + 1) \]

其中,\(c_j\) 就是能到达的最下的下边缘。拆式子搞前缀和即可。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// LOJ2387.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 1e5 + 200, mod = 1e9 + 7, inv2 = (mod + 1) >> 1;
typedef long long ll;
int n, yi[MAX_N], lft[MAX_N], rig[MAX_N], row[MAX_N], col[MAX_N], pre[MAX_N];
int main()
{
scanf("%d", &n);
for (int i = 1, x, y; i <= n; i++)
scanf("%d%d", &x, &y), yi[x] = y;
int val = n;
for (int i = 0; i < n; i++)
val = min(val, yi[i] + 1), lft[i + 1] = val;
val = 0;
for (int i = n - 1; i >= 0; i--)
val = max(val, yi[i]), rig[i] = val;
for (int i = 1, ptr = n - 1; i < n; i++)
{
while (i > rig[ptr])
ptr--;
col[i] = ptr + 1, row[i] = lft[i] - 1;
}
int ans = 0;
for (int i = 1; i < n; i++)
pre[i] = (0LL + pre[i - 1] + 1LL * col[i] * i % mod) % mod;
for (int i = 1; i < n; i++)
ans = (0LL + ans + (pre[rig[i]] + mod - pre[lft[i] - 1]) % mod) % mod;
// printf("%d\n", ans);
for (int i = 1; i < n; i++)
ans = (0LL + ans + mod - 1LL * i * (lft[i] + rig[i]) % mod * (rig[i] - lft[i] + 1) % mod * inv2 % mod) % mod;
// printf("%d\n", ans);
for (int i = 1; i < n; i++)
ans = (0LL + ans + 1LL * row[i] * i % mod * (rig[i] - lft[i] + 1) % mod) % mod;
// printf("%d\n", ans);
for (int i = 1; i < n; i++)
pre[i] = (0LL + pre[i - 1] + col[i]) % mod;
for (int i = 1; i < n; i++)
ans = (0LL + ans + mod - 1LL * row[i] * ((0LL + pre[rig[i]] + mod - pre[lft[i] - 1]) % mod) % mod) % mod;
printf("%d\n", ans);
return 0;
}
// LOJ2387.cpp #include <bits/stdc++.h> using namespace std; const int MAX_N = 1e5 + 200, mod = 1e9 + 7, inv2 = (mod + 1) >> 1; typedef long long ll; int n, yi[MAX_N], lft[MAX_N], rig[MAX_N], row[MAX_N], col[MAX_N], pre[MAX_N]; int main() { scanf("%d", &n); for (int i = 1, x, y; i <= n; i++) scanf("%d%d", &x, &y), yi[x] = y; int val = n; for (int i = 0; i < n; i++) val = min(val, yi[i] + 1), lft[i + 1] = val; val = 0; for (int i = n - 1; i >= 0; i--) val = max(val, yi[i]), rig[i] = val; for (int i = 1, ptr = n - 1; i < n; i++) { while (i > rig[ptr]) ptr--; col[i] = ptr + 1, row[i] = lft[i] - 1; } int ans = 0; for (int i = 1; i < n; i++) pre[i] = (0LL + pre[i - 1] + 1LL * col[i] * i % mod) % mod; for (int i = 1; i < n; i++) ans = (0LL + ans + (pre[rig[i]] + mod - pre[lft[i] - 1]) % mod) % mod; // printf("%d\n", ans); for (int i = 1; i < n; i++) ans = (0LL + ans + mod - 1LL * i * (lft[i] + rig[i]) % mod * (rig[i] - lft[i] + 1) % mod * inv2 % mod) % mod; // printf("%d\n", ans); for (int i = 1; i < n; i++) ans = (0LL + ans + 1LL * row[i] * i % mod * (rig[i] - lft[i] + 1) % mod) % mod; // printf("%d\n", ans); for (int i = 1; i < n; i++) pre[i] = (0LL + pre[i - 1] + col[i]) % mod; for (int i = 1; i < n; i++) ans = (0LL + ans + mod - 1LL * row[i] * ((0LL + pre[rig[i]] + mod - pre[lft[i] - 1]) % mod) % mod) % mod; printf("%d\n", ans); return 0; }
// LOJ2387.cpp
#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 1e5 + 200, mod = 1e9 + 7, inv2 = (mod + 1) >> 1;

typedef long long ll;

int n, yi[MAX_N], lft[MAX_N], rig[MAX_N], row[MAX_N], col[MAX_N], pre[MAX_N];

int main()
{
    scanf("%d", &n);
    for (int i = 1, x, y; i <= n; i++)
        scanf("%d%d", &x, &y), yi[x] = y;
    int val = n;
    for (int i = 0; i < n; i++)
        val = min(val, yi[i] + 1), lft[i + 1] = val;
    val = 0;
    for (int i = n - 1; i >= 0; i--)
        val = max(val, yi[i]), rig[i] = val;

    for (int i = 1, ptr = n - 1; i < n; i++)
    {
        while (i > rig[ptr])
            ptr--;
        col[i] = ptr + 1, row[i] = lft[i] - 1;
    }

    int ans = 0;
    for (int i = 1; i < n; i++)
        pre[i] = (0LL + pre[i - 1] + 1LL * col[i] * i % mod) % mod;
    for (int i = 1; i < n; i++)
        ans = (0LL + ans + (pre[rig[i]] + mod - pre[lft[i] - 1]) % mod) % mod;
    // printf("%d\n", ans);
    for (int i = 1; i < n; i++)
        ans = (0LL + ans + mod - 1LL * i * (lft[i] + rig[i]) % mod * (rig[i] - lft[i] + 1) % mod * inv2 % mod) % mod;
    // printf("%d\n", ans);
    for (int i = 1; i < n; i++)
        ans = (0LL + ans + 1LL * row[i] * i % mod * (rig[i] - lft[i] + 1) % mod) % mod;
    // printf("%d\n", ans);
    for (int i = 1; i < n; i++)
        pre[i] = (0LL + pre[i - 1] + col[i]) % mod;
    for (int i = 1; i < n; i++)
        ans = (0LL + ans + mod - 1LL * row[i] * ((0LL + pre[rig[i]] + mod - pre[lft[i] - 1]) % mod) % mod) % mod;
    printf("%d\n", ans);
    return 0;
}

 

Leave a Reply

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