# 「csp校内训练 2019-11-04」解题报告

## T1、腿部挂件

### $Description$：

Jim 是一个热爱打游戏的小伙子，可惜他的游戏水平不太行，以至于经常在游戏里被别人欺负。而且 Jim 不仅游戏玩的菜，他还很爱喷人，但是由于自己的垃圾操作，他又喷不过别人。为了改善这种局面，Jim 决定成为一个腿部挂件 (俗称抱大腿)。

$1 \leq N \leq 200000, 1 \leq Q \leq 200000$
$0 \leq a_i \leq 10^9$
$0 \leq X \leq 10^9,0 \leq L \leq R < N$

### $Source$：

#include <cstdio>
#include <cstring>
#include <algorithm>
int in() {
int x = 0; char c = getchar(); bool f = 0;
while (c < '0' || c > '9')
f |= c == '-', c = getchar();
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }

const int N = 2e5 + 5;

struct info {
int l, r, x, id;
inline bool operator < (const info &y) const {
return this->r < y.r;
}
} b[N];
int a[N], res[N];

struct trie {
int c[N * 31][2], last[N * 31], tot, rt;
void insert(const int k, const int tim) {
int p = rt;
for (int i = 30; i >= 0; --i) {
int t = (k >> i) & 1;
if (!c[p][t])
c[p][t] = ++tot;
last[c[p][t]] = tim;
p = c[p][t];
}
}
int query_max(const int k, const int tim) {
int p = rt, ret = 0;
for (int i = 30; i >= 0; --i) {
int t = (k >> i) & 1;
if (last[c[p][t ^ 1]] >= tim) {
ret |= (1 << i);
p = c[p][t ^ 1];
} else {
p = c[p][t];
}
}
return ret;
}
} T;

int n, q;

int main() {
//freopen("in", "r", stdin);
freopen("hugclose.in", "r", stdin);
freopen("hugclose.out", "w", stdout);
n = in(), q = in();
for (int i = 1; i <= n; ++i)
a[i] = in();
for (int i = 1; i <= q; ++i)
b[i].x = in(), b[i].l = in() + 1, b[i].r = in() + 1, b[i].id = i;
std::sort(b + 1, b + 1 + q);
for (int i = 1, pos = 1; i <= q; ++i) {
for (; pos <= b[i].r; T.insert(a[pos], pos), ++pos);
res[b[i].id] = T.query_max(b[i].x, b[i].l);
}
for (int i = 1; i <= q; ++i)
printf("%d\n", res[i]);
return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
int in() {
int x = 0; char c = getchar(); bool f = 0;
while (c < '0' || c > '9')
f |= c == '-', c = getchar();
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }

const int N = 2e5 + 5;

struct persistable_trie {
int c[N * 31][2], rt[N];
int tot;
int insert(int pre, int k) {
int p, ret;
p = ret = ++tot;
for (int i = 30; i >= 0; --i) {
int t = (k >> i) & 1;
c[p][t ^ 1] = c[pre][t ^ 1];
c[p][t] = ++tot;
p = c[p][t], pre = c[pre][t];
}
return ret;
}
int query_max(int pre, int p, int k) {
int ret = 0;
for (int i = 30; i >= 0; --i) {
int t = (k >> i) & 1;
if (c[p][t ^ 1] ^ c[pre][t ^ 1]) {
ret |= (1 << i);
p = c[p][t ^ 1], pre = c[pre][t ^ 1];
} else {
p = c[p][t], pre = c[pre][t];
}
}
return ret;
}
} T;
int n, q;

int main() {
//freopen("in", "r", stdin);
freopen("hugclose.in", "r", stdin);
freopen("hugclose.out", "w", stdout);
n = in(), q = in();
for (int i = 1; i <= n; ++i)
T.rt[i] = T.insert(T.rt[i - 1], in());
while (q--) {
int x = in(), l = in(), r = in();
printf("%d\n", T.query_max(T.rt[l], T.rt[r + 1], x));
}
return 0;
}


## T2、走夜路

### $Description$：

Jim 是一个胆小的男生，可是每天他都要学习到很晚才能回家，而且他回家的路上没有路灯。

Jim 非常怕黑，万幸的是他还有一个手电筒可以用，我们设手电筒的电量上限为 $T$

$N \leq 500000$
$2 \leq N \leq 500000 , 1 \leq T \leq 10^9$
$1 \leq d_i, p_i \leq 1000000$

### $Source$：

#include <cstdio>
#include <cstring>
#include <algorithm>
int in() {
int x = 0; char c = getchar(); bool f = 0;
while (c < '0' || c > '9')
f |= c == '-', c = getchar();
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }

const int N = 5e5 + 5;

int n, T, p[N], fr[N];
long long d[N];

void prep() {
static int sta[N], tp;
sta[0] = n + 1;
for (int i = n; i; --i) {
for (; tp && p[sta[tp]] > p[i]; --tp);
fr[i] = sta[tp];
sta[++tp] = i;
}
}

long long work() {
long long ret = 0, rest = 0;
for (int i = 1; i <= n; ) {
if (d[fr[i]] - d[i] > T) {
ret += std::max(0ll, std::min(1ll * T, d[n + 1] - d[i]) - rest) * p[i];
chk_max(rest, std::min(1ll * T, d[n + 1] - d[i]));
if (d[i + 1] - d[i] > T)
return -1;
rest -= d[i + 1] - d[i];
++i;
} else {
ret += std::max(0ll, d[fr[i]] - d[i] - rest) * p[i];
chk_max(rest, d[fr[i]] - d[i]);
rest -= d[fr[i]] - d[i];
i = fr[i];
}
}
return ret;
}

int main() {
//freopen("in", "r", stdin);
freopen("wayhome.in", "r", stdin);
freopen("wayhome.out", "w", stdout);
n = in(), T = in();
for (int i = 1; i <= n; ++i)
d[i + 1] = d[i] + in(), p[i] = in();
prep();
printf("%lld\n", work());
return 0;
}


## T3、宝石专家

### $Description$：

Jim是一位宝石收藏品行家,

Jim 发现他所有的宝石中竟然有不少是完全相同的的，我们规定每个宝石都有一个特征值 $a_i$ ，当两个宝石特征值相等时及认为两个宝石相同。
Jim 发现两个相同的宝石离得越接近越明显。

Jim 现在有 $m$ 个问题，他想问你在编号 $l$$r$ 这一区间里的所有宝石中，两个相同宝石的最近距离是多少(两个宝石的距离是它们编号的绝对值之差)。

$1 \leq n,m \leq 2 \times 10^5$
$-10^9 \leq a_i \leq 10^9$
$1 \leq l_j \leq r_j \leq n$

### $Source$：

#include <cstdio>
#include <cstring>
#include <algorithm>
int in() {
int x = 0; char c = getchar(); bool f = 0;
while (c < '0' || c > '9')
f |= c == '-', c = getchar();
while (c >= '0' && c <= '9')
x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return f ? -x : x;
}
template<typename T>inline void chk_min(T &_, T __) { _ = _ < __ ? _ : __; }
template<typename T>inline void chk_max(T &_, T __) { _ = _ > __ ? _ : __; }

const int N = 2e5 + 5;

struct info {
int l, r, id;
inline bool operator < (const info &y) const {
return this->r < y.r;
}
} b[N];
int a[N], res[N], last[N];
int n, m, nn;

struct segment_tree {
int min[N << 2], M;
void init() {
memset(min, -1, sizeof(min));
for (M = 1; M - 2 < n; M <<= 1);
}
void modify(int p, int k) {
for (p += M; p; p >>= 1)
if (!~min[p])
min[p] = k;
else
chk_min(min[p], k);
}
int query(int l, int r) {
int ret = -1;
for (l += M - 1, r += M + 1; l ^ r ^ 1; l >>= 1, r >>= 1) {
if ((~l & 1) && ~min[l ^ 1]) {
if (!~ret)
ret = min[l ^ 1];
else
chk_min(ret, min[l ^ 1]);
}
if ((r & 1) && ~min[r ^ 1]) {
if (!~ret)
ret = min[r ^ 1];
else
chk_min(ret, min[r ^ 1]);
}
}
return ret;
}
} T;

void prep() {
static int tmp[N];
memcpy(tmp, a, sizeof(a));
std::sort(tmp + 1, tmp + 1 + n);
nn = std::unique(tmp + 1, tmp + 1 + n) - tmp - 1;
for (int i = 1; i <= n; ++i)
a[i] = std::lower_bound(tmp + 1, tmp + 1 + nn, a[i]) - tmp;
T.init();
std::sort(b + 1, b + 1 + m);
}

int main() {
//freopen("in", "r", stdin);
freopen("jewel.in", "r", stdin);
freopen("jewel.out", "w", stdout);
n = in(), m = in();
for (int i = 1; i <= n; ++i)
a[i] = in();
for (int i = 1; i <= m; ++i)
b[i].l = in(), b[i].r = in(), b[i].id = i;
prep();
for (int i = 1, pos = 1; i <= m; ++i) {
for (; pos <= b[i].r; ++pos) {
if (last[a[pos]])
T.modify(last[a[pos]], pos - last[a[pos]]);
last[a[pos]] = pos;
}
res[b[i].id] = T.query(b[i].l, b[i].r);
}
for (int i = 1; i <= m; ++i)
printf("%d\n", res[i]);
return 0;
}

posted @ 2019-11-04 22:20  15owzLy1  阅读(...)  评论(...编辑  收藏