RAINBOWA
签到。
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 105;
int n, a[MAXN];
inline bool Solve(int l, int r, int t)
{
if (t == 7)
{
for (int i = l; i <= r; i ++)
if (a[i] ^ 7)
return false;
return true;
}
if (a[l] != t || a[r] != t)
return false;
while (l <= r && a[l] == t && a[r] == t)
l ++, r --;
if (l > r)
return false;
return Solve(l, r, t + 1);
}
inline void Sol()
{
n = Read();
for (int i = 1; i <= n; i ++)
a[i] = Read();
puts(Solve(1, n, 1) ? "yes" : "no");
}
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
for (int T = Read(); T; T --)
Sol();
return 0;
}
CHEFMOVR
签到。
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 200005;
int n, m;
LL a[MAXN];
inline void Sol()
{
n = Read(), m = Read();
for (int i = 1; i <= n; i ++)
a[i] = Read();
LL ave = 0, ans = 0;
for (int i = 1; i <= m; i ++)
{
LL tot = 0, cnt = 0;
for (int j = i; j <= n; j += m)
tot += a[j], cnt ++;
if (tot % cnt)
{
puts("-1");
return ;
}
tot /= cnt;
if (i == 1)
ave = tot;
else if (ave ^ tot)
{
puts("-1");
return ;
}
}
for (int i = 1; i <= n; i ++)
a[i] -= ave;
for (int i = 1; i <= n; i ++)
ans += abs(a[i]), a[i + m] += a[i];
printf("%lld\n", ans);
}
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
for (int T = Read(); T; T --)
Sol();
return 0;
}
GCAC
签到。
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 1005;
int n, m, a[MAXN], b[MAXN], c[MAXN], h[MAXN];
char s[MAXN];
inline void Sol()
{
LL d = 0, e = 0, f = 0;
n = Read(), m = Read();
for (int i = 1; i <= n; i ++)
a[i] = Read();
for (int i = 1; i <= m; i ++)
b[i] = Read(), c[i] = Read(), h[i] = 0;
for (int i = 1; i <= n; i ++)
{
scanf("%s", s + 1);
int g = 0;
for (int j = 1; j <= m; j ++)
if (s[j] == '1' && c[j] && b[j] >= a[i] && b[j] > b[g])
g = j;
if (g)
d ++, e += b[g], c[g] --, h[g] = 1;
}
for (int i = 1; i <= m; i ++)
f += !h[i];
printf("%lld %lld %lld\n", d, e, f);
}
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
for (int T = Read(); T; T --)
Sol();
return 0;
}
PALINGAM
分类讨论一下。
如果A的字符集是B的子集,那么A出什么B都能拼出来,B赢。
否则如果B是A的子集,A可以先出一个B没有的,然后B随便出什么A都可以拼这个,A赢。
然后如果存在相交的,如果A有某个B没有的字符出现了
2
次,那么A赢。
其他情况,B一定可以拖到结束,B赢。
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 505;
int n, a[26], b[26];
char s[MAXN], t[MAXN];
inline void Sol()
{
scanf("%s%s", s + 1, t + 1); n = strlen(s + 1);
for (int i = 0; i < 26; i ++)
a[i] = b[i] = 0;
for (int i = 1; i <= n; i ++)
a[s[i] - 'a'] ++, b[t[i] - 'a'] ++;
bool flag = true;
for (int i = 0; i < 26; i ++)
if (a[i] && !b[i])
flag = false;
if (flag)
{
puts("B");
return ;
}
flag = true;
for (int i = 0; i < 26; i ++)
if (b[i] && !a[i])
flag = false;
if (flag)
{
puts("A");
return ;
}
for (int i = 0; i < 26; i ++)
if (a[i] > 1 && !b[i])
flag = true;
if (flag)
puts("A");
else
puts("B");
}
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
for (int T = Read(); T; T --)
Sol();
return 0;
}
CHEFFA
假设
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 505;
const int mod = 1e9 + 7;
int n, m, a[MAXN], f[MAXN][MAXN][MAXN];
inline void Sol()
{
mset(f, 0);
n = Read(), m = max(n + 50, n << 1);
for (int i = 1; i <= n; i ++)
a[i] = Read();
for (int i = n + 1; i <= m; i ++)
a[i] = 0;
f[0][0][0] = 1;
for (int i = 0; i < m; i ++)
for (int j = 0; j <= 500; j ++)
for (int k = 0; k <= 500; k ++)
if (f[i][j][k])
for (int l = 0; l <= a[i + 1] + k - j; l ++)
f[i + 1][l][j] = (f[i + 1][l][j] + f[i][j][k]) % mod;
int ret = 0;
for (int i = 0; i <= 500; i ++)
for (int j = 0; j <= 500; j ++)
ret = (ret + f[m][i][j]) % mod;
printf("%d\n", ret);
}
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
for (int T = Read(); T; T --)
Sol();
return 0;
}
STRINGRA
这个条件本质上就是
prei
到
i−1
之间的向
i
连一条有向边。
这个结论很显然,就不证了。
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 100005;
int n, m, a[MAXN];
vector <int> adj[MAXN];
inline void Sol()
{
int cnt = 0;
n = Read(), m = Read();
for (int i = 0; i <= n; i ++)
adj[i].clear();
for (int i = 1, x, y; i <= m; i ++)
x = Read(), y = Read(), adj[y].pb(x);
if (adj[0].size())
{
puts("-1");
return ;
}
for (int i = 1; i <= n; i ++)
{
sort(adj[i].begin(), adj[i].end());
if (!adj[i].size())
{
puts("-1");
return ;
}
for (int j = 1; j < adj[i].size(); j ++)
if (adj[i][j] - adj[i][j - 1] ^ 1)
{
puts("-1");
return ;
}
if (i - adj[i][adj[i].size() - 1] ^ 1)
{
puts("-1");
return ;
}
if (!adj[i][0])
a[i] = ++ cnt;
else
{
a[i] = a[adj[i][0]];
for (int j = adj[i][0] + 1; j < i; j ++)
if (a[i] == a[j])
{
puts("-1");
return ;
}
}
}
for (int i = 1; i <= n; i ++)
printf("%d%c", a[i], i == n ? '\n' : ' ');
}
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
for (int T = Read(); T; T --)
Sol();
return 0;
}
HILLJUMP
如果我们知道了
求
nexti
我们也可以分块,注意到
100
这个条件,我们可以暴力单调栈求出块,同时块大小大于
100
,所以一次修改最多影响四个块。
每次暴力修改用个单调栈求
nexti
。
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 100005;
const int MAXM = 325;
const int blk = 320;
int n, m, Q, bel[MAXN], nxt[MAXN], br[MAXN], bc[MAXN], st[425], tp;
LL a[MAXN], tag[MAXM];
inline void Rebuild(int id)
{
if (id < 0 || id > m)
return ;
int l = id * blk + 1, r = min((id + 1) * blk, n);
for (int i = l; i <= r; i ++)
{
while (tp && a[st[tp]] + tag[id] < a[i] + tag[id])
nxt[st[tp --]] = i;
st[++ tp] = i;
}
for (int i = r + 1; i <= min(n, r + 100); i ++)
while (tp && a[st[tp]] + tag[id] < a[i] + tag[id + 1])
nxt[st[tp --]] = i;
while (tp)
nxt[st[tp --]] = n + 101;
for (int i = l; i <= r; i ++)
if (nxt[i] - i > 100)
nxt[i] = i;
for (int i = r; i >= l; i --)
if (nxt[i] > r || nxt[i] == i)
br[i] = i, bc[i] = 0;
else
br[i] = br[nxt[i]], bc[i] = bc[nxt[i]] + 1;
}
inline int Query()
{
int x = Read(), k = Read();
while (true)
{
if (nxt[x] == x)
return x;
k --, x = nxt[x];
if (!k)
return x;
if (k <= bc[x])
{
while (k --)
x = nxt[x];
return x;
}
k -= bc[x], x = br[x];
}
}
inline void Modify()
{
int l = Read(), r = Read(), k = Read(), bl = bel[l], br = bel[r];
if (bl == br)
{
for (int i = l; i <= r; i ++)
a[i] += k;
Rebuild(bl);
Rebuild(bl - 1);
return ;
}
for (int i = l; i <= (bl + 1) * blk; i ++)
a[i] += k;
for (int i = br * blk + 1; i <= r; i ++)
a[i] += k;
for (int i = bl + 1; i < br; i ++)
tag[i] += k;
Rebuild(bl); Rebuild(bl - 1); Rebuild(br); Rebuild(br - 1);
}
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
n = Read(); Q = Read();
for (int i = 1; i <= n; i ++)
bel[i] = (i - 1) / blk, a[i] = Read();
m = bel[n];
for (int i = 0; i <= m; i ++)
Rebuild(i);
while (Q --)
if (Read() == 1)
printf("%d\n", Query());
else
Modify();
}
WALKBT
注意到答案本质上是树链的并。
那么我们需要一个
set
,然后用总长度减去相邻两个元素的
lcp
就是答案。
这启示我们用主席树维护哈希值来查询
lcp
和比较大小。
每个
1
最多贡献一次进位,暴力处理就好了。
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 100005;
const int MAXM = 8000005;
const int bas1 = 233;
const int bas2 = 2333;
const int mod1 = 1e9 + 7;
const int mod2 = 1e9 + 9;
struct Node { int l, r; pii h; } e[MAXM];
int n, Q, tot, rt[MAXN], pw1[MAXN], pw2[MAXN], cnt;
LL ans;
inline void Build(int &x, int l, int r)
{
e[x = ++ tot].h = mp(0, 0);
if (l == r)
return ;
int mid = l + r >> 1;
Build(e[x].l, l, mid); Build(e[x].r, mid + 1, r);
}
inline bool Modify(int &x, int l, int r, int p)
{
int y = x; e[x = ++ tot] = e[y];
if (l == r)
return e[x].h.xx ^= 1, e[x].h.yy ^= 1;
int mid = l + r >> 1, ret = p <= mid ? Modify(e[x].l, l, mid, p) : Modify(e[x].r, mid + 1, r, p);
e[x].h.xx = (1LL * e[e[x].l].h.xx * pw1[r - mid] + e[e[x].r].h.xx) % mod1;
e[x].h.yy = (1LL * e[e[x].r].h.yy * pw2[r - mid] + e[e[x].r].h.yy) % mod2;
return ret;
}
inline int Cmp(int x, int y, int l, int r)
{
if (e[x].h == e[y].h)
return 0;
if (l == r)
return e[x].h.xx ? 1 : -1;
int mid = l + r >> 1;
if (e[e[x].l].h == e[e[y].l].h)
return Cmp(e[x].r, e[y].r, mid + 1, r);
return Cmp(e[x].l, e[y].l, l, mid);
}
inline int Lcp(int x, int y, int l, int r)
{
if (e[x].h == e[y].h)
return r - l + 1;
if (l == r)
return 0;
int mid = l + r >> 1;
if (e[e[x].l].h != e[e[y].l].h)
return Lcp(e[x].l, e[y].l, l, mid);
return mid - l + 1 + Lcp(e[x].r, e[y].r, mid + 1, r);
}
struct Info
{
int r;
bool operator < (const Info &b) const { return Cmp(r, b.r, 1, n) < 0; }
};
set <Info> S;
inline void Sol()
{
tot = cnt = 0; ans = 1; S.clear();
n = Read(), Q = Read();
pw1[0] = pw2[0] = 1;
for (int i = 1; i <= n; i ++)
pw1[i] = 1LL * pw1[i - 1] * bas1 % mod1, pw2[i] = 1LL * pw2[i - 1] * bas2 % mod2;
Build(rt[0], 1, n);
for (int i = 1; i <= Q; i ++)
{
char opt[5];
scanf("%s", opt);
if (opt[0] == '!')
{
int x = n - Read(); cnt ++;
rt[cnt] = rt[cnt - 1];
while (!Modify(rt[cnt], 1, n, x) && x > 1)
x --;
Info tmp; tmp.r = rt[cnt];
if (S.empty())
ans += n;
else
{
auto it = S.lower_bound(tmp), jt = it;
if (it == S.end())
jt --, ans += n - Lcp(rt[cnt], jt -> r, 1, n);
else if (it == S.begin())
ans += n - Lcp(rt[cnt], it -> r, 1, n);
else
{
jt --;
ans += Lcp(it -> r, jt -> r, 1, n);
ans += n;
ans -= Lcp(rt[cnt], it -> r, 1, n);
ans -= Lcp(rt[cnt], jt -> r, 1, n);
}
}
S.insert(tmp);
}
else
printf("%lld\n", ans);
}
}
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
for (int T = Read(); T; T --)
Sol();
return 0;
}
FLOWERPO
如果
我们尝试让两边独立,但两边显然不独立,比如
1,2,12,16,100
,
C=3
,这里
16
的半径至少是
84
,显然左边就被覆盖完了。
我们发现这种使得两边独立的操作只会有一次,并且之前一定是从
C
朝这个方向引爆。
那么我们预处理前缀,后缀的DP值,和
当然这个DP还可以斜率优化。
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
inline int Read()
{
int x = 0, f = 1, c = getchar();
for (; !isdigit(c); c = getchar())
if (c == '-')
f = -1;
for (; isdigit(c); c = getchar())
x = x * 10 + c - '0';
return x * f;
}
const int MAXN = 3005;
int n, m, b, c, a[MAXN], s[MAXN], nxt[MAXN][MAXN];
LL f[MAXN][MAXN], g[MAXN][MAXN], ans;
inline void Dp(int t)
{
static int q[MAXN], ql, qr;
static LL y[MAXN];
q[ql = qr = 1] = 0;
for (int i = 1; i <= m; i ++)
{
while (ql < qr && y[q[ql + 1]] - y[q[ql]] < 2LL * s[i] * (s[q[ql + 1]] - s[q[ql]]))
ql ++;
f[t][i] = f[t - 1][q[ql]] + 1LL * (s[i] - s[q[ql]]) * (s[i] - s[q[ql]]);
y[i] = f[t - 1][i] + 1LL * s[i] * s[i];
while (ql < qr && (__int128)(y[i] - y[q[qr]]) * (s[q[qr]] - s[q[qr - 1]]) <= (__int128)(y[q[qr]] - y[q[qr - 1]]) * (s[i] - s[q[qr]]))
qr --;
q[++ qr] = i;
}
}
inline int Sol()
{
n = Read(), b = Read(), c = Read() - 1; ans = 1LL << 60;
for (int i = 0; i < n; i ++)
a[i] = Read();
for (int i = 0; i < n; i ++)
for (int j = 1, l = i, r = i; j < n; nxt[i][j ++] = l * n + r)
if (l && (r == n - 1 || a[i] - a[l] <= a[r] - a[i]))
l --;
else
r ++;
for (int i = 1; i <= n; i ++)
f[0][i] = 1LL << 60;
m = 0;
for (int i = 1; i < n; i ++)
s[++ m] = a[i] - a[0];
for (int i = 1; i <= b; i ++)
Dp(i);
for (int i = 0; i < c; i ++)
for (int j = 0; j <= b; j ++)
g[i][j] = f[j][i];
m = 0;
for (int i = n - 2; ~i; i --)
s[++ m] = a[n - 1] - a[i];
for (int i = 1; i <= b; i ++)
Dp(i);
for (int i = n - 1; i > c; i --)
for (int j = 0; j <= b; j ++)
g[i][j] = f[j][n - 1 - i];
m = 0;
for (int i = c - 1; ~i; i --)
s[++ m] = a[c] - a[i];
for (int i = 1; i <= b; i ++)
Dp(i);
for (int i = c - 1; ~i; i --)
for (int j = 1; j < n; j ++)
for (int k = 1; k < b; k ++)
{
int l = nxt[i][j] / n, r = nxt[i][j] - l * n, val = max(a[i] - a[l], a[r] - a[i]);
if ((l < i || !l) && (r > c || r == n - 1))
ans = min(ans, f[k][c - i] + 1LL * val * val + g[l][b - k - 1] + g[r][b - k - 1]);
}
m = 0;
for (int i = c + 1; i < n; i ++)
s[++ m] = a[i] - a[c];
for (int i = 1; i <= b; i ++)
Dp(i);
for (int i = c + 1; i < n; i ++)
for (int j = 1; j < n; j ++)
for (int k = 1; k < b; k ++)
{
int l = nxt[i][j] / n, r = nxt[i][j] - l * n, val = max(a[i] - a[l], a[r] - a[i]);
if ((l < c || !l) && (r > i || r == n - 1))
ans = min(ans, f[k][i - c] + 1LL * val * val + g[l][b - k - 1] + g[r][b - k - 1]);
}
for (int i = 0; i < n; i ++)
{
int l = nxt[c][i] / n, r = nxt[c][i] - l * n, val = max(a[c] - a[l], a[r] - a[c]);
if ((l < c || !l) && (r > c || r == n - 1))
ans = min(ans, 1LL * val * val + g[l][b - 1] + g[r][b - 1]);
}
printf("%lld\n", ans);
}
int main()
{
#ifdef wxh010910
freopen("data.in", "r", stdin);
#endif
for (int T = Read(); T; T --)
Sol();
return 0;
}
Challenge是个工业题,懒得写了。