您的位置:首页 > 其它

CodeForces Gym 101741 简要题解

2018-03-04 21:08 531 查看

Three Arrays:

枚举 aiai ,求出当前 bb 的合法区间和 cc 的合法区间,并且要求 bb 中的数在 cc 中的合法区间与枚举的 aa 中的数的合法区间有交,然后用前缀和维护一下。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}

const int N = 500005;

int d, p, q, r, a
, b
, c
, u
, v
;
LL ans, L
, R
;

int Main() {
ans = 0;
for (int i = 1; i <= p; ++i) {
Read(a[i]);
}
for (int i = 1; i <= q; ++i) {
Read(b[i]);
}
for (int i = 1; i <= r; ++i) {
Read(c[i]);
}
for (int i = 1, c_l = 1, c_r = 0; i <= q; ++i) {
for (; c_l <= r && c[c_l] < b[i] - d; ++c_l);
for (; c_r < r && c[c_r + 1] <= b[i] + d; ++c_r);
u[i] = c_l, v[i] = c_r;
L[i] = L[i - 1] + c_l;
R[i] = R[i - 1] + c_r;
}
for (int i = 1, b_l = 1, b_r = 0, c_l = 1, c_r = 0, pos = 0; i <= p; ++i) {
for (; c_l <= r && c[c_l] < a[i] - d; ++c_l);
for (; c_r < r && c[c_r + 1] <= a[i] + d; ++c_r);
for (; b_l <= q && (v[b_l] < c_l || b[b_l] < a[i] - d); ++b_l);
for (; b_r < q && b[b_r + 1] <= a[i] + d && u[b_r + 1] <= c_r; ++b_r);
for (; pos < q && b[pos + 1] <= a[i]; ++pos);
if (b_l <= pos) {
ans += R[pos] - R[b_l - 1];
ans -= 1LL * (c_l - 1) * (pos - b_l + 1);
}
if (pos + 1 <= b_r) {
ans += 1LL * (c_r + 1) * (b_r - pos);
ans -= L[b_r] - L[pos];
}
}
printf("%lld\n", ans);
return 0;
}

int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
while (~scanf("%d %d %d %d", &d, &p, &q, &r)) {
Main();
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}


Expected Shopping:

留坑,不打算填。

Cover the Paths:

贪心放即可。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}

const int N = 100005;

vector <int> adj
;
set <int> s
;
int n, m, tot;
bool ans
;

inline void DFS(int x, int p) {
for (auto y : adj[x]) {
if (y != p) {
DFS(y, x);
if (s[x].size() < s[y].size()) {
swap(s[x], s[y]);
}
for (auto i : s[y]) {
if (s[x].find(i) != s[x].end()) {
ans[x] = true;
break;
} else {
s[x].insert(i);
}
}
}
}
if (ans[x]) {
++tot, s[x].clear();
}
}

int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n);
for (int i = 1, x, y; i < n; ++i) {
Read(x), Read(y);
adj[x].pb(y), adj[y].pb(x);
}
Read(m);
for (int i = 1, x, y; i <= m; ++i) {
Read(x), Read(y);
if (x == y) {
ans[x] = true;
} else {
s[x].insert(i), s[y].insert(i);
}
}
DFS(1, 0);
printf("%d\n", tot);
for (int i = 1; i <= n; ++i) {
if (ans[i]) {
printf("%d", i);
putchar(--tot ? ' ' : '\n');
}
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}


Elevator:

如果 ti≤tj,ai≤ajti≤tj,ai≤aj 那么 ii 是没用的,可以去掉。

fi=min(ti,fj)+2aj+1fi=min(ti,fj)+2aj+1 ,线段树优化即可。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}

const int N = 200005;

int n, top, a
, b
, sta
;
LL f
, val[2][N << 2];

inline void Build(int x, int l, int r) {
val[0][x] = val[1][x] = 1LL << 60;
if (l == r) {
return ;
}
int mid = l + r >> 1;
Build(x << 1, l, mid), Build(x << 1 | 1, mid + 1, r);
}

inline void Modify(int o, int x, int l, int r, int ql, int qr, LL v) {
if (ql > qr) {
return ;
}
if (l == ql && r == qr) {
CheckMin(val[o][x], v);
return ;
}
CheckMin(val[o][x << 1], val[o][x]), CheckMin(val[o][x << 1 | 1], val[o][x]);
int mid = l + r >> 1;
if (qr <= mid) {
Modify(o, x << 1, l, mid, ql, qr, v);
} else if (ql > mid) {
Modify(o, x << 1 | 1, mid + 1, r, ql, qr, v);
} else {
Modify(o, x << 1, l, mid, ql, mid, v), Modify(o, x << 1 | 1, mid + 1, r, mid + 1, qr, v);
}
}

inline LL Query(int o, int x, int l, int r, int p) {
if (l == r) {
return val[o][x];
}
CheckMin(val[o][x << 1], val[o][x]), CheckMin(val[o][x << 1 | 1], val[o][x]);
int mid = l + r >> 1;
if (p <= mid) {
return Query(o, x << 1, l, mid, p);
} else {
return Query(o, x << 1 | 1, mid + 1, r, p);
}
}

int Main() {
top = 0;
for (int i = 1; i <= n; ++i) {
Read(a[i]), Read(b[i]);
for (; top && b[sta[top]] <= b[i]; --top);
sta[++top] = i;
}
for (int i = 1; i <= top; ++i) {
a[i] = a[sta[i]], b[i] = b[sta[i]];
}
n = top;
Build(1, 1, n);
for (int i = 0; i <= n; ++i) {
if (i) {
f[i] = min(Query(0, 1, 1, n, i), Query(1, 1, 1, n, i) + a[i]);
} else {
f[i] = 0;
}
int pos = lower_bound(a + 1, a + n + 1, (int)min(f[i], 1LL << 30)) - a;
Modify(0, 1, 1, n, i + 1, pos - 1, f[i] + 2 * b[i + 1]);
Modify(1, 1, 1, n, pos, n, 2 * b[i + 1]);
}
printf("%lld\n", f
);
return 0;
}

int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
while (~scanf("%d", &n)) {
Main();
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}


Code-Cola Plants:

从 bb 向 aa 连两条边,那么第一组边相当于每个点入度为 11 ,第二组边相当于每个点出度为 11 。

构造一个左边 2n2n 个点,右边 mm 个点的二分图,那么就是要求一个最大匹配。

注意到右边每个点度数都是 22 ,所以直接在左边连边,相当于求一个环套树森林。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}

const int N = 1000005;

int n, m, s, t, ql, qr, cnt, d
, f
, q
, ans
;
vector <pii> adj
;
vector <int> seq;
bool v
;

inline int Find(int x) {
while (x != f[x]) {
x = f[x] = f[f[x]];
}
return x;
}

int Main() {
for (int i = 1; i <= n << 1; ++i) {
f[i] = i, v[i] = false, d[i] = 0, adj[i].clear();
}
f[s + n] = t, v[t] = true, cnt = 2, d[t] = d[s + n] = 2;
adj[t].pb(mp(s + n, 0)), adj[s + n].pb(mp(t, 0));
adj[t].pb(mp(s + n, 0)), adj[s + n].pb(mp(t, 0));
for (int i = 1, p, q, x, y; i <= m; ++i) {
Read(p), Read(q), q += n, x = Find(p), y = Find(q);
if (x == y) {
if (!v[x]) {
adj[p].pb(mp(q, i)), adj[q].pb(mp(p, i)), ++cnt;
++d[p], ++d[q], v[x] = true;
}
} else if (!v[x] || !v[y]) {
adj[p].pb(mp(q, i)), adj[q].pb(mp(p, i)), ++cnt;
++d[p], ++d[q], f[x] = y, v[y] |= v[x];
}
ans[i] = -1;
}
if (cnt != n << 1) {
puts("NO");
return 0;
}
puts("YES"), ql = qr = 0;
for (int i = 1; i <= n << 1; ++i) {
if (d[i] == 1) {
q[++qr] = i;
}
v[i] = false;
}
while (ql < qr) {
int x = q[++ql];
v[x] = true;
for (auto e : adj[x]) {
if (!v[e.X]) {
ans[e.Y] = x > n;
if (--d[e.X] == 1) {
q[++qr] = e.X;
}
}
}
}
for (int i = 1; i <= n << 1; ++i) {
if (!v[i]) {
seq.clear();
for (int x = i, p; x; ) {
v[x] = true, seq.pb(x), p = 0;
for (auto e : adj[x]) {
if (!v[e.X]) {
p = e.X;
break;
}
}
x = p;
}
for (int i = 0, m = seq.size(); i < m; ++i) {
for (auto e : adj[seq[i]]) {
if (e.X == seq[(i + 1) % m] && !~ans[e.Y]) {
ans[e.Y] = seq[i] > n;
break;
}
}
}
}
}
for (int i = 1, t = 0; i <= m; ++i) {
if (ans[i] == 1) {
printf("%d%c", i, ++t == n - 1 ? '\n' : ' ');
}
}
for (int i = 1, t = 0; i <= m; ++i) {
if (!ans[i]) {
printf("%d%c", i, ++t == n - 1 ? '\n' : ' ');
}
}
return 0;
}

int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
while (~scanf("%d %d %d %d", &n, &m, &s, &t)) {
Main();
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}


GCD:

考虑随机一个保留的数 x=aix=ai ,每次随机有 1212 以上的正确率,多次随机即可。

将这个数分解质因数,然后在 gcd(ai,x)gcd(ai,x) 处打上标记,那么每个点实际的标记是它倍数的标记之和。

本质上是一个高维前缀和,单次 σ0(x)×ω(x)σ0(x)×ω(x) 的复杂度可以承受。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}

const int N = 100005;

int n, m, cnt, deg
;
LL ans, a
, pri
;
map <LL, int> val;
vector <LL> seq;

inline int Rand() {
return rand() << 15 | rand();
}

inline LL RandLL() {
return (LL)Rand() << 30 | Rand();
}

inline LL Qul(LL x, LL y, LL mod) {
return ((x * y - (LL)(((LD)x * y + 0.5) / mod) * mod) % mod + mod) % mod;
}

inline LL Qow(LL x, LL y, LL mod) {
LL r = 1;
for (; y; y >>= 1, x = Qul(x, x, mod)) {
if (y & 1) {
r = Qul(r, x, mod);
}
}
return r;
}

inline bool MillerRabin(LL n) {
if (n == 2) {
return true;
}
if (n < 2 || !(n & 1)) {
return false;
}
LL a, x, y, u = n - 1;
int t = 0;
for (; !(u & 1); u >>= 1, ++t);
for (int i = 0; i < 10; ++i) {
a = RandLL() % (n - 1) + 1, x = Qow(a, u, n);
for (int j = 0; j < t; ++j, x = y) {
if ((y = Qul(x, x, n)) == 1 && x != 1 && x != n - 1) {
return false;
}
}
if (x != 1) {
return false;
}
}
return true;
}

inline LL PollardRho(LL a, LL c) {
LL k = 2, x = RandLL() % a, y = x, p = 1;
for (LL i = 1; p == 1; ++i) {
x = (Qul(x, x, a) + c) % a, p = __gcd(abs(x - y), a);
if (i == k) {
y = x, k <<= 1;
}
}
return p;
}

inline void Divide(LL x) {
if (x == 1) {
return ;
}
if (MillerRabin(x)) {
pri[cnt++] = x;
return ;
}
LL p = x;
while (p >= x) {
p = PollardRho(x, RandLL() % (x - 1));
}
Divide(p), Divide(x / p);
}

inline void DFS(int x, LL v) {
if (x == cnt) {
val[v] = 0, seq.pb(v);
return ;
}
for (int i = 0; i <= deg[x]; ++i) {
DFS(x + 1, v), v *= pri[x];
}
}

inline void Solve(LL x) {
cnt = 0, Divide(x);
sort(pri, pri + cnt);
cnt = unique(pri, pri + cnt) - pri;
LL tmp = x;
for (int i = 0; i < cnt; ++i) {
for (deg[i] = 0; tmp % pri[i] == 0; tmp /= pri[i], ++deg[i]);
}
val.clear(), seq.clear(), DFS(0, 1);
for (int i = 0; i < n; ++i) {
++val[__gcd(a[i], x)];
}
for (int i = 0; i < cnt; ++i) {
for (int j = seq.size() - 1; ~j; --j) {
if (seq[j] % pri[i] == 0) {
val[seq[j] / pri[i]] += val[seq[j]];
}
}
}
random_shuffle(seq.begin(), seq.end());
for (int i = 0; i < seq.size(); ++i) {
if (val[seq[i]] >= n - m) {
CheckMax(ans, seq[i]);
}
}
}

int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
srand(time(0));
Read(n), Read(m);
for (int i = 0; i < n; ++i) {
Read(a[i]);
}
while ((double)clock() / CLOCKS_PER_SEC < 3.5) {
Solve(a[Rand() % n]);
}
printf("%lld\n", ans);
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}


Berland Post:

二分 TT ,跑差分约束。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}

const int N = 2005;
const int inf = 0x3f3f3f3f;

struct Edge {
int p, v;
double w;
} e[N << 1];

int n, m, e_cnt, a
, b
, c
, d
, cnt
, hed
;
double dis
;
bool vis
;
char s
;

inline void AddEdge(int x, int y, double w) {
e[++e_cnt] = {y, hed[x], w}, hed[x] = e_cnt;
}

inline bool Check(double t) {
e_cnt = 0;
for (int i = 0; i <= n; ++i) {
hed[i] = 0;
}
for (int i = 1; i <= n; ++i) {
if (c[i] != INT_MAX) {
AddEdge(0, i, c[i]), AddEdge(i, 0, -c[i]);
}
}
for (int i = 1; i <= m; ++i) {
AddEdge(b[i], a[i], t - d[i]);
}
queue <int> q;
for (int i = 0; i <= n; ++i) {
dis[i] = 10000000, q.push(i), vis[i] = true, cnt[i] = 0;
}
dis[0] = 0;
while (!q.empty()) {
int x = q.front();
q.pop(), vis[x] = false;
for (int i = hed[x]; i; i = e[i].v) {
if (CheckMin(dis[e[i].p], dis[x] + e[i].w)) {
if (++cnt[e[i].p] > n) {
return false;
}
if (!vis[e[i].p]) {
vis[e[i].p] = true, q.push(e[i].p);
}
}
}
}
return true;
}

int Main() {
for (int i = 1; i <= n; ++i) {
scanf("%s", s);
if (s[0] == '?') {
c[i] = INT_MAX;
} else {
sscanf(s, "%d", &c[i]);
}
}
for (int i = 1; i <= m; ++i) {
Read(a[i]), Read(b[i]), Read(d[i]);
}
double l = 0, r = inf;
while (r - l > 1e-5) {
double mid = (l + r) / 2;
if (Check(mid)) {
r = mid;
} else {
l = mid;
}
}
printf("%lf\n", r), Check(r);
for (int i = 1; i <= n; ++i) {
printf("%lf%c", dis[i], i == n ? '\n' : ' ');
}
return 0;
}

int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
while (~scanf("%d %d", &n, &m)) {
Main();
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}


Compressed Spanning Subtrees:

考虑每次询问除了 ii 点的剩下 n−1n−1 个点,可以知道 ii 是不是叶子,这里需要询问 ii 次。

任选一个叶子 rootroot 当根,对于剩下的每对叶节点 xx 和非叶节点 yy ,问一次 root,x,yroot,x,y 可以知道 yy 是不是 xx 的祖先。

将每个非叶节点按照子树大小排序之后可以知道所有边了。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}

const int N = 105;

vector <int> lef, oth, seq, adj
;
int n, rot, siz
, par
;
bool plc
, anc

;

inline int Query() {
int cnt = 0, ret = 0;
for (int i = 1; i <= n; ++i) {
if (plc[i]) {
++cnt;
}
}
printf("? %d", cnt);
for (int i = 1; i <= n; ++i) {
if (plc[i]) {
printf(" %d", i);
}
}
putchar(10);
fflush(stdout);
Read(ret);
return ret;
}

inline int DFS(int x) {
for (auto y : adj[x]) {
if (y != par[x]) {
par[y] = x, DFS(y);
}
}
}

int main() {
#ifdef wxh010910
#endif
Read(n);
if (n == 2) {
puts("! 1");
fflush(stdout);
return 0;
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
plc[j] = i != j;
}
if (Query() == n - 1) {
if (!rot) {
rot = i;
} else {
lef.pb(i);
}
} else {
oth.pb(i);
}
}
for (auto x : lef) {
for (auto y : oth) {
for (int i = 1; i <= n; ++i) {
plc[i] = i == rot || i == x || i == y;
}
if (Query() == 3) {
anc[x][y] = true, ++siz[y];
}
}
}
for (auto x : lef) {
seq.clear();
for (int i = 1; i <= n; ++i) {
if (anc[x][i]) {
seq.pb(i);
}
}
sort(seq.begin(), seq.end(), [&](const int &x, const int &y) { return siz[x] < siz[y]; });
par[x] = seq[0], par[seq.back()] = rot;
for (int i = 1; i < seq.size(); ++i) {
par[seq[i - 1]] = seq[i];
}
}
for (int i = 1; i <= n; ++i) {
if (i != rot) {
adj[par[i]].pb(i), adj[i].pb(par[i]), par[i] = 0;
}
}
DFS(1), putchar('!');
for (int i = 2; i <= n; ++i) {
printf(" %d", par[i]);
}
putchar(10);
fflush(stdout);
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}


Prefix-free Queries:

预处理后缀数组,每次询问按字典序排序之后可以建出树,树形DP即可。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}

const int N = 400005;
const int M = 20;

int n, m, q, mod, top, g
, h
, L
, arr
, siz
, sta
, rnk
, f[M]
;
vector <int> adj
;
char s
;

inline void Build() {
static int a
, b
, t
, cnt_a
, cnt_b
;
for (int i = 1; i <= n; ++i) {
++cnt_a[s[i]];
}
for (int i = 1; i < 26; ++i) {
cnt_a[i] += cnt_a[i - 1];
}
for (int i = n; i; --i) {
arr[cnt_a[s[i]]--] = i;
}
rnk[arr[1]] = 1;
for (int i = 2; i <= n; ++i) {
rnk[arr[i]] = rnk[arr[i - 1]] + (s[arr[i]] != s[arr[i - 1]]);
}
for (int l = 1; rnk[arr
] < n; l <<= 1) {
for (int i = 0; i <= n; ++i) {
cnt_a[i] = cnt_b[i] = 0;
}
for (int i = 1; i <= n; ++i) {
++cnt_a[a[i] = rnk[i]], ++cnt_b[b[i] = i + l > n ? 0 : rnk[i + l]];
}
for (int i = 1; i <= n; ++i) {
cnt_a[i] += cnt_a[i - 1], cnt_b[i] += cnt_b[i - 1];
}
for (int i = n; i; --i) {
t[cnt_b[b[i]]--] = i;
}
for (int i = n; i; --i) {
arr[cnt_a[a[t[i]]]--] = t[i];
}
rnk[arr[1]] = 1;
for (int i = 2; i <= n; ++i) {
rnk[arr[i]] = rnk[arr[i - 1]] + (a[arr[i]] != a[arr[i - 1]] || b[arr[i]] != b[arr[i - 1]]);
}
}
for (int i = 1, j = 0; i <= n; ++i) {
for (j -= j > 0; rnk[i] != 1 && s[i + j] == s[arr[rnk[i] - 1] + j]; ++j);
h[rnk[i]] = j;
}
}

inline int LCP(int x, int y) {
if (x == y) {
return n - x + 1;
}
x = rnk[x], y = rnk[y];
if (x > y) {
swap(x, y);
}
++x;
int k = L[y - x];
return min(f[k][x], f[k][y - (1 << k) + 1]);
}

struct String {
int l, r;

bool operator < (const String &b) const {
int lcp = min(min(r - l + 1, b.r - b.l + 1), LCP(l, b.l));
if (b.r - b.l + 1 == lcp) {
return false;
} else if (r - l + 1 == lcp) {
return true;
} else {
return s[l + lcp] < s[b.l + lcp];
}
}

bool operator == (const String &b) const {
return r - l + 1 == b.r - b.l + 1 && LCP(l, b.l) >= r - l + 1;
}
} str
;

inline bool Prefix(String a, String b) {
return a.r - a.l + 1 == min(min(a.r - a.l + 1, b.r - b.l + 1), LCP(a.l, b.l));
}

inline void DFS(int x) {
g[x] = 1;
for (auto y : adj[x]) {
DFS(y), g[x] = 1LL * g[x] * (g[y] + 1) % mod;
}
g[x] = (g[x] + siz[x] - 1) % mod;
}

int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n), Read(q), siz[0] = 1;
scanf("%s", s + 1), s[n + 1] = 26;
for (int i = 1; i <= n; ++i) {
s[i] -= 'a';
}
Build();
for (int i = 1; i <= n; ++i) {
f[0][i] = h[i];
}
for (int j = 1; j < M; ++j) {
for (int i = 1; i + (1 << j) - 1 <= n; ++i) {
f[j][i] = min(f[j - 1][i], f[j - 1][i + (1 << j - 1)]);
}
}
for (int i = 2; i <= n; ++i) {
L[i] = L[i >> 1] + 1;
}
for (int i = 1; i <= q; ++i) {
Read(m), Read(mod);
for (int i = 1; i <= m; ++i) {
Read(str[i].l), Read(str[i].r);
}
sort(str + 1, str + m + 1);
sta[top = 1] = 1;
for (int i = 2; i <= m; ++i) {
if (!(str[i] == str[i - 1])) {
sta[++top] = i;
}
}
for (int i = 1; i <= top; ++i) {
siz[i] = i == top ? m - sta[i] + 1 : sta[i + 1] - sta[i];
}
m = top;
for (int i = 1; i <= m; ++i) {
str[i] = str[sta[i]];
}
top = 0;
for (int i = 0; i <= m; ++i) {
adj[i].clear();
}
for (int i = 1; i <= m; ++i) {
for (; top && !Prefix(str[sta[top]], str[i]); --top);
adj[sta[top]].pb(i), sta[++top] = i;
}
DFS(0);
printf("%d\n", g[0]);
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}


Subsequence Sum Queries:

分治,每次处理跨过 [mid,mid+1][mid,mid+1] 的答案,预处理背包即可。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}

const int N = 200005;
const int M = 25;
const int mod = 1e9 + 7;

struct Node {
int l, r, i;
} s
, t
;

int n, m, q, a
, ans
, f
[M];

inline void Solve(int l, int r, int ql, int qr) {
if (ql > qr) {
return ;
}
if (l == r) {
for (int i = ql; i <= qr; ++i) {
ans[s[i].i] = (!a[l]) + 1;
}
return ;
}
int mid = l + r >> 1, tl = ql - 1, tr = qr + 1;
for (int j = 0; j < m; ++j) {
f[mid][j] = (!j) + (j == a[mid]);
f[mid + 1][j] = (!j) + (j == a[mid + 1]);
}
for (int i = mid - 1; i >= l; --i) {
for (int j = 0; j < m; ++j) {
f[i][j] = f[i + 1][j];
}
for (int j = 0; j < m; ++j) {
f[i][(j + a[i]) % m] = (f[i][(j + a[i]) % m] + f[i + 1][j]) % mod;
}
}
for (int i = mid + 2; i <= r; ++i) {
for (int j = 0; j < m; ++j) {
f[i][j] = f[i - 1][j];
}
for (int j = 0; j < m; ++j) {
f[i][(j + a[i]) % m] = (f[i][(j + a[i]) % m] + f[i - 1][j]) % mod;
}
}
for (int i = ql; i <= qr; ++i) {
if (s[i].l <= mid && s[i].r > mid) {
for (int j = 0; j < m; ++j) {
ans[s[i].i] = (1LL * f[s[i].l][j] * f[s[i].r][(m - j) % m] + ans[s[i].i]) % mod;
}
} else if (s[i].r <= mid) {
t[++tl] = s[i];
} else {
t[--tr] = s[i];
}
}
for (int i = ql; i <= tl; ++i) {
s[i] = t[i];
}
for (int i = tr; i <= qr; ++i) {
s[i] = t[i];
}
Solve(l, mid, ql, tl), Solve(mid + 1, r, tr, qr);
}

int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n), Read(m);
for (int i = 1; i <= n; ++i) {
Read(a[i]), a[i] %= m;
}
Read(q);
for (int i = 1; i <= q; ++i) {
Read(s[i].l), Read(s[i].r), s[i].i = i;
}
Solve(1, n, 1, q);
for (int i = 1; i <= q; ++i) {
printf("%d\n", ans[i]);
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}


Consistent Occurrences:

本质不同的长度只有根号个,对于每种长度将哈希值存下来,询问直接查询。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}

const int N = 100005;
const int bas[2] = {2333, 2339};
const int mod[2] = {1000000007, 1000000009};

int n, m, all, cur, l
, r
, ans
, len
, h[2]
, pwd[2]
;
map <pii, pii> cnt;
char s
, t
;

inline void Solve(int len) {
cnt.clear();
for (int i = len; i <= n; ++i) {
pii val = mp((h[0][i] - 1LL * h[0][i - len] * pwd[0][len] % mod[0] + mod[0]) % mod[0], (h[1][i] - 1LL * h[1][i - len] * pwd[1][len] % mod[1] + mod[1]) % mod[1]);
if (cnt.find(val) == cnt.end()) {
cnt[val] = mp(1, i);
} else {
if (i - cnt[val].Y < len) {
continue;
} else {
++cnt[val].X, cnt[val].Y = i;
}
}
}
for (int i = 1; i <= m; ++i) {
if (r[i] - l[i] + 1 == len) {
pii cur = mp(0, 0);
for (int j = l[i]; j <= r[i]; ++j) {
cur = mp((1LL * cur.X * bas[0] + t[j]) % mod[0], (1LL * cur.Y * bas[1] + t[j]) % mod[1]);
}
ans[i] = cnt[cur].X;
}
}
}

int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n), Read(m);
scanf("%s", s + 1);
pwd[0][0] = pwd[1][0] = 1;
for (int j = 0; j < 2; ++j) {
for (int i = 1; i <= n; ++i) {
h[j][i] = (1LL * h[j][i - 1] * bas[j] + s[i]) % mod[j];
pwd[j][i] = 1LL * pwd[j][i - 1] * bas[j] % mod[j];
}
}
for (int i = 1; i <= m; ++i) {
scanf("%s", t + cur + 1);
l[i] = cur + 1, len[i] = strlen(t + cur + 1);
cur += len[i], r[i] = cur;
}
sort(len + 1, len + m + 1), all = unique(len + 1, len + m + 1) - len - 1;
for (int i = 1; i <= all; ++i) {
Solve(len[i]);
}
for (int i = 1; i <= m; ++i) {
printf("%d\n", ans[i]);
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}


Increasing Costs:

建出最短路DAG,就是询问删掉一条边 11 不能到几个点。

将边拆点,建出灭绝树,就是询问子树点数。

#include <bits/stdc++.h>

using namespace std;

#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;

template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}

template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}

template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}

const int N = 400005;
const int M = 20;

struct Edge {
int p, v, w, i;
} e[N << 1];

int n, m, ql, qr, e_cnt, d
, q
, ans
, dep
, hed
, f[M]
;
vector <int> adj
;

inline void Dijkstra() {
priority_queue <pair <LL, int>> q;
static bool vis
;
static LL dis
;
for (int i = 1; i <= n; ++i) {
dis[i] = LLONG_MAX;
}
dis[1] = 0, q.push(mp(0, 1));
while (!q.empty()) {
int x = q.top().Y;
q.pop();
if (vis[x]) {
continue;
}
for (int i = hed[x]; i; i = e[i].v) {
if (CheckMin(dis[e[i].p], dis[x] + e[i].w)) {
q.push(mp(-dis[e[i].p], e[i].p));
}
}
}
for (int x = 1; x <= n; ++x) {
for (int i = hed[x]; i; i = e[i].v) {
if (dis[e[i].p] == dis[x] + e[i].w) {
adj[e[i].p + m].pb(e[i].i);
adj[e[i].i].pb(x + m);
++d[e[i].i], ++d[x + m];
}
}
}
}

inline int LCA(int x, int y) {
if (dep[x] < dep[y]) {
swap(x, y);
}
if (dep[x] != dep[y]) {
for (int i = 0; i < M; ++i) {
if (dep[x] - dep[y] >> i & 1) {
x = f[i][x];
}
}
}
if (x == y) {
return x;
}
for (int i = M - 1; ~i; --i) {
if (f[i][x] != f[i][y]) {
x = f[i][x], y = f[i][y];
}
}
return f[0][x];
}

int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n), Read(m);
for (int i = 1, u, v, w; i <= m; ++i) {
Read(u), Read(v), Read(w);
e[++e_cnt] = {v, hed[u], w, i}, hed[u] = e_cnt;
e[++e_cnt] = {u, hed[v], w, i}, hed[v] = e_cnt;
}
Dijkstra();
for (int i = m + 1; i <= n + m; ++i) {
if (!d[i]) {
q[++qr] = i;
}
}
while (ql <= qr) {
int x = q[++ql];
for (auto y : adj[x]) {
if (!--d[y]) {
q[++qr] = y;
}
}
}
for (int i = qr - 1; i; --i) {
int x = q[i], cur = adj[x][0];
for (auto y : adj[x]) {
cur = LCA(cur, y);
}
f[0][x] = cur, dep[x] = dep[cur] + 1;
for (int j = 1; j < M; ++j) {
f[j][x] = f[j - 1][f[j - 1][x]];
}
}
for (int i = 1; i < qr; ++i) {
int x = q[i];
ans[x] += x > m;
ans[f[0][x]] += ans[x];
}
for (int i = 1; i <= m; ++i) {
printf("%d\n", ans[i]);
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: