Contest Info
Solved | A | B | C | D | E | F | G | H | I | J | K | L |
---|---|---|---|---|---|---|---|---|---|---|---|---|
7 / 12 | O | - | - | - | Ø | O | Ø | - | Ø | O | - | Ø |
- O 在比赛中通过
- Ø 赛后通过
- ! 尝试了但是失败了
- - 没有尝试
Solutions
A. Total Eclipse
是个假题。。直接并查集倒着做就行。
Code
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 100007
#define MAXM 200007
int b[MAXN];
int hd[MAXN], nxt[MAXM], to[MAXM], en=0;
int d[MAXN];
int mv[MAXN], fa[MAXN];
inline void adde(int a, int b) {
nxt[en]=hd[a]; hd[a]=en; to[en]=b; en++;
}
inline bool cmp(int x, int y) {
return b[x]>b[y];
}
inline int findfa(int x) {
int f=x; int v;
while(fa[f]!=f) f=fa[f];
v=mv[f];
while(f!=x) {
int t=fa[x];
mv[x]=v;
fa[x]=f;
x=t;
}
return f;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T; cin>>T;
while(0<T--) {
en=0;
int n,m; cin>>n>>m;
for(int i=1; i<=n; i++) cin>>b[i];
for(int i=1; i<=n; i++) mv[i]=b[i];
for(int i=1; i<=n; i++) d[i]=i;
for(int i=1; i<=n; i++) fa[i]=i;
memset(hd+1,-1,sizeof(int)*n);
for(int i=0; i<m; i++) {
int u,v; cin>>u>>v;
if(b[u]>b[v]) swap(u,v);
adde(u,v);
}
sort(d+1,d+1+n,cmp);
long long ans=0;
for(int j=1; j<=n; j++) {
int x=d[j];
for(int i=hd[x]; ~i; i=nxt[i]) {
int t=to[i];
int f1=findfa(x), f2=findfa(t);
ans+=mv[f2]-mv[f1];
fa[f1]=f2;
mv[f2]=mv[f1];
}
}
for(int x=1; x<=n; x++) {
int f=findfa(x);
ans+=mv[f]; mv[f]=0;
}
cout<<ans<<'
';
}
}
E. New Equipments
每一个二次曲线都有一个最优解取值范围,我们对于每个左边的点连接(geq n)个“较优解”,根据hall定理一定存在完美匹配。
之后直接暴力冲费用流就行。
Code
// Author : heyuhhh
// Created Time : 2020/07/23 22:39:10
#include<bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 5000 + 5, M = 50000 + 5;
struct E {
int from, to, cp;
ll v;
E() {}
E(int f, int t, int cp, ll v) : from(f), to(t), cp(cp), v(v) {}
};
ll f[N];
struct MCMF {
int n, m, s, t;
vector<E> edges;
vector<int> G[N];
bool inq[N];
ll d[N];
int p[N], a[M];
void init(int _n, int _s, int _t) {
n = _n; s = _s; t = _t;
for(int i = 0; i <= n; i++) G[i].clear();
edges.clear(); m = 0;
}
void addedge(int from, int to, int cap, ll cost) {
edges.emplace_back(from, to, cap, cost);
edges.emplace_back(to, from, 0, -cost);
G[from].push_back(m++);
G[to].push_back(m++);
}
bool BellmanFord(int &flow, ll &cost) {
for(int i = 0; i <= n; i++) d[i] = 6e18;
memset(inq, 0, sizeof inq);
d[s] = 0, a[s] = INF, inq[s] = true;
queue<int> Q; Q.push(s);
while (!Q.empty()) {
int u = Q.front(); Q.pop();
inq[u] = false;
for (int& idx: G[u]) {
E &e = edges[idx];
if (e.cp && d[e.to] > d[u] + e.v) {
d[e.to] = d[u] + e.v;
p[e.to] = idx;
a[e.to] = min(a[u], e.cp);
if (!inq[e.to]) {
Q.push(e.to);
inq[e.to] = true;
}
}
}
}
if (d[t] == 6e18) return false;
flow += a[t];
cost += 1ll * a[t] * d[t];
int u = t;
while (u != s) {
edges[p[u]].cp -= a[t];
edges[p[u] ^ 1].cp += a[t];
u = edges[p[u]].from;
}
return true;
}
ll go() {
int flow = 0;
ll cost = 0;
int t = 0;
while (BellmanFord(flow, cost)) {
f[++t] = cost;
}
return cost;
}
} MM;
int a[N], b[N];
ll c[N];
int n, m;
void run() {
map<int, int> mp;
cin >> n >> m;
int tot = n;
for (int i = 1; i <= n; i++) {
cin >> a[i] >> b[i] >> c[i];
if (b[i] >= 0) {
for (int j = 1; j <= min(m, n + 1); j++) {
if (mp.find(j) == mp.end()) {
mp[j] = ++tot;
}
}
} else {
int t = - b[i] / (2 * a[i]);
for (int j = max(t - n, 1); j <= min(m, t + n); j++) {
if (mp.find(j) == mp.end()) {
mp[j] = ++tot;
}
}
}
}
MM.init(tot + 1, 0, tot + 1);
for (int i = 1; i <= n; i++) {
MM.addedge(0, i, 1, 0);
}
for (auto& it : mp) {
MM.addedge(it.se, tot + 1, 1, 0);
}
for (int i = 1; i <= n; i++) {
if (b[i] >= 0) {
for (int j = 1; j <= min(m, n + 1); j++) {
MM.addedge(i, mp[j], 1, 1ll * a[i] * j * j + 1ll * b[i] * j + c[i]);
}
} else {
int t = - b[i] / (2 * a[i]);
for (int j = max(t - n, 1); j <= min(m, t + n); j++) {
MM.addedge(i, mp[j], 1, 1ll * a[i] * j * j + 1ll * b[i] * j + c[i]);
}
}
}
MM.go();
for (int i = 1; i <= n; i++) {
cout << f[i] << "
"[i == n];
}
}
int main() {
#ifdef Local
freopen("input.in", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
int T; cin >> T; while(T--)
run();
return 0;
}
F. The Oculus
题意:
给出(A,B,C),每个数都用斐波纳契数列来表示,即(x=a_1cdot F_1+a_2cdot F_2+cdots+a_ncdot F_n,a_iin{0,1})。
现有(Acdot B=C),但(C)会有一个(1)变为了(0),所以现在就要找到哪一个位置变为了(0)。
思路:
直接做是不好做的,并没有什么比较好用的性质能够套在这题上面。
对于这种不需要知道精确解的问题,其实可以用hash来判断大小、相等关系。这是一个比较常见的思路。
所以就直接上hash就行。。
Code
// Author : heyuhhh
// Created Time : 2020/07/23 16:24:33
#include<bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 2e6 + 5;
const int p[3] = {998244353, 100000259, 10001093};
#define FI(n) FastIO::read(n)
#define FO(n) FastIO::write(n)
#define Flush FastIO::Fflush()
namespace FastIO {
const int SIZE = 1 << 16;
char buf[SIZE], obuf[SIZE], str[60];
int bi = SIZE, bn = SIZE, opt;
double D[] = {0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, 0.00000001, 0.000000001, 0.0000000001};
int read(char *s) {
while (bn) {
for (; bi < bn && buf[bi] <= ' '; bi++);
if (bi < bn) break;
bn = fread(buf, 1, SIZE, stdin);
bi = 0;
}
int sn = 0;
while (bn) {
for (; bi < bn && buf[bi] > ' '; bi++) s[sn++] = buf[bi];
if (bi < bn) break;
bn = fread(buf, 1, SIZE, stdin);
bi = 0;
}
s[sn] = 0;
return sn;
}
bool read(int& x) {
int n = read(str), bf = 0;
if (!n) return 0;
int i = 0; if (str[i] == '-') bf = 1, i++; else if (str[i] == '+') i++;
for (x = 0; i < n; i++) x = x * 10 + str[i] - '0';
if (bf) x = -x;
return 1;
}
bool read(long long& x) {
int n = read(str), bf;
if (!n) return 0;
int i = 0; if (str[i] == '-') bf = -1, i++; else bf = 1;
for (x = 0; i < n; i++) x = x * 10 + str[i] - '0';
if (bf < 0) x = -x;
return 1;
}
void write(int x) {
if (x == 0) obuf[opt++] = '0';
else {
if (x < 0) obuf[opt++] = '-', x = -x;
int sn = 0;
while (x) str[sn++] = x % 10 + '0', x /= 10;
for (int i = sn - 1; i >= 0; i--) obuf[opt++] = str[i];
}
if (opt >= (SIZE >> 1)) {
fwrite(obuf, 1, opt, stdout);
opt = 0;
}
}
void write(long long x) {
if (x == 0) obuf[opt++] = '0';
else {
if (x < 0) obuf[opt++] = '-', x = -x;
int sn = 0;
while (x) str[sn++] = x % 10 + '0', x /= 10;
for (int i = sn - 1; i >= 0; i--) obuf[opt++] = str[i];
}
if (opt >= (SIZE >> 1)) {
fwrite(obuf, 1, opt, stdout);
opt = 0;
}
}
void write(unsigned long long x) {
if (x == 0) obuf[opt++] = '0';
else {
int sn = 0;
while (x) str[sn++] = x % 10 + '0', x /= 10;
for (int i = sn - 1; i >= 0; i--) obuf[opt++] = str[i];
}
if (opt >= (SIZE >> 1)) {
fwrite(obuf, 1, opt, stdout);
opt = 0;
}
}
void write(char x) {
obuf[opt++] = x;
if (opt >= (SIZE >> 1)) {
fwrite(obuf, 1, opt, stdout);
opt = 0;
}
}
void Fflush() { if (opt) fwrite(obuf, 1, opt, stdout); opt = 0;}
};
int fib[N][3];
void init() {
fib[1][0] = fib[1][1] = fib[1][2] = 1;
fib[2][0] = fib[2][1] = fib[2][2] = 2;
for (int k = 0; k < 3; k++) {
for (int i = 3; i < N; i++) {
fib[i][k] = (fib[i - 1][k] + fib[i - 2][k]) % p[k];
}
}
}
int a[N], b[N], c[N];
int sa[3], sb[3], sc[3];
void run() {
for (int k = 0; k < 3; k++) {
sa[k] = sb[k] = sc[k] = 0;
}
int na, nb, nc;
FI(na);
for (int i = 1; i <= na; i++) {
FI(a[i]);
for (int k = 0; k < 3; k++) {
if (a[i]) {
sa[k] = (sa[k] + fib[i][k]) % p[k];
}
}
}
FI(nb);
for (int i = 1; i <= nb; i++) {
FI(b[i]);
for (int k = 0; k < 3; k++) {
if (b[i]) {
sb[k] = (sb[k] + fib[i][k]) % p[k];
}
}
}
FI(nc);
for (int i = 1; i <= nc; i++) {
FI(c[i]);
for (int k = 0; k < 3; k++) {
if (c[i]) {
sc[k] = (sc[k] + fib[i][k]) % p[k];
}
}
}
map<int, int> mp;
for (int k = 0; k < 3; k++) {
int t = (1ll * sa[k] * sb[k] % p[k] - sc[k] + p[k]) % p[k];
for (int i = 1; i < nc; i++) {
if (fib[i][k] == t) {
++mp[i];
if (mp[i] == 3) {
FO(i), FO('
');
return;
}
}
}
}
}
int main() {
#ifdef Local
freopen("input.in", "r", stdin);
#endif
init();
int T; cin >> T; while(T--)
run();
Flush;
return 0;
}
G. In Search of Gold
二分一下直径然后树形dp判断是否可行即可,类似于树上背包的问题,注意加上减枝,即对size取min,这样复杂度可以做到(O(nklog(ans)))。
Code
// Author : heyuhhh
// Created Time : 2020/07/24 10:09:05
#include<bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 20000 + 5, M = 25;
int n, k;
struct Edge {
int v, next, a, b;
}e[N << 1];
int head[N], tot;
void adde(int u, int v, int a, int b) {
e[tot] = Edge{v, head[u], a, b};
head[u] = tot++;
}
#define FI(n) FastIO::read(n)
#define FO(n) FastIO::write(n)
#define Flush FastIO::Fflush()
namespace FastIO {
const int SIZE = 1 << 16;
char buf[SIZE], obuf[SIZE], str[60];
int bi = SIZE, bn = SIZE, opt;
double D[] = {0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, 0.00000001, 0.000000001, 0.0000000001};
int read(char *s) {
while (bn) {
for (; bi < bn && buf[bi] <= ' '; bi++);
if (bi < bn) break;
bn = fread(buf, 1, SIZE, stdin);
bi = 0;
}
int sn = 0;
while (bn) {
for (; bi < bn && buf[bi] > ' '; bi++) s[sn++] = buf[bi];
if (bi < bn) break;
bn = fread(buf, 1, SIZE, stdin);
bi = 0;
}
s[sn] = 0;
return sn;
}
bool read(int& x) {
int n = read(str), bf = 0;
if (!n) return 0;
int i = 0; if (str[i] == '-') bf = 1, i++; else if (str[i] == '+') i++;
for (x = 0; i < n; i++) x = x * 10 + str[i] - '0';
if (bf) x = -x;
return 1;
}
bool read(long long& x) {
int n = read(str), bf;
if (!n) return 0;
int i = 0; if (str[i] == '-') bf = -1, i++; else bf = 1;
for (x = 0; i < n; i++) x = x * 10 + str[i] - '0';
if (bf < 0) x = -x;
return 1;
}
void write(int x) {
if (x == 0) obuf[opt++] = '0';
else {
if (x < 0) obuf[opt++] = '-', x = -x;
int sn = 0;
while (x) str[sn++] = x % 10 + '0', x /= 10;
for (int i = sn - 1; i >= 0; i--) obuf[opt++] = str[i];
}
if (opt >= (SIZE >> 1)) {
fwrite(obuf, 1, opt, stdout);
opt = 0;
}
}
void write(long long x) {
if (x == 0) obuf[opt++] = '0';
else {
if (x < 0) obuf[opt++] = '-', x = -x;
int sn = 0;
while (x) str[sn++] = x % 10 + '0', x /= 10;
for (int i = sn - 1; i >= 0; i--) obuf[opt++] = str[i];
}
if (opt >= (SIZE >> 1)) {
fwrite(obuf, 1, opt, stdout);
opt = 0;
}
}
void write(unsigned long long x) {
if (x == 0) obuf[opt++] = '0';
else {
int sn = 0;
while (x) str[sn++] = x % 10 + '0', x /= 10;
for (int i = sn - 1; i >= 0; i--) obuf[opt++] = str[i];
}
if (opt >= (SIZE >> 1)) {
fwrite(obuf, 1, opt, stdout);
opt = 0;
}
}
void write(char x) {
obuf[opt++] = x;
if (opt >= (SIZE >> 1)) {
fwrite(obuf, 1, opt, stdout);
opt = 0;
}
}
void Fflush() { if (opt) fwrite(obuf, 1, opt, stdout); opt = 0;}
};
ll dp[N][M], t[M];
int sz[N];
bool flag;
void dfs(int u, int fa, ll x) {
if (flag) return;
sz[u] = 1;
dp[u][0] = 0;
for (int i = head[u]; i != -1; i = e[i].next) {
int v = e[i].v, a = e[i].a, b = e[i].b;
if (v == fa) continue;
dfs(v, u, x);
if (flag) return;
int up = min(sz[u] + sz[v] - 1, k);
for (int j = 0; j <= up; j++) {
t[j] = x + 1;
}
for (int j = 0; j < sz[u]; j++) {
for (int p = 0; p < sz[v] && p + j <= up; p++) {
if (dp[u][j] + dp[v][p] + b <= x) {
t[j + p] = min(t[j + p], max(dp[u][j], dp[v][p] + b));
}
if (dp[u][j] + dp[v][p] + a <= x) {
t[j + p + 1] = min(t[j + p + 1], max(dp[u][j], dp[v][p] + a));
}
}
}
sz[u] += sz[v];
bool ok = false;
for (int j = 0; j <= up; j++) {
dp[u][j] = t[j];
if (t[j] <= x) ok = true;
}
if (ok = false) {
dp[1][k] = x + 1;
flag = true;
return;
}
}
}
void run() {
FI(n), FI(k);
for (int i = 1; i <= n; i++) {
head[i] = -1;
}
tot = 0;
ll l = 1, r = 2, mid;
for (int i = 1; i < n; i++) {
int u, v, a, b;
FI(u), FI(v), FI(a), FI(b);
r += max(a, b);
adde(u, v, a, b);
adde(v, u, a, b);
}
while (l < r) {
mid = (l + r) >> 1;
flag = false;
dfs(1, 0, mid);
if (dp[1][k] <= mid) r = mid;
else l = mid + 1;
}
FO(l), FO('
');
}
int main() {
#ifdef Local
freopen("input.in", "r", stdin);
#endif
int T; FI(T); while(T--)
run();
Flush;
return 0;
}
I. It's All Squares
发现暴力似乎可以过。。那就暴力吧。。
Code
// Author : heyuhhh
// Created Time : 2020/07/24 19:03:09
#include<bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 400 + 5;
#define FI(n) FastIO::read(n)
#define FO(n) FastIO::write(n)
#define Flush FastIO::Fflush()
namespace FastIO {
const int SIZE = 1 << 16;
char buf[SIZE], obuf[SIZE], str[60];
int bi = SIZE, bn = SIZE, opt;
double D[] = {0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, 0.00000001, 0.000000001, 0.0000000001};
int read(char *s) {
while (bn) {
for (; bi < bn && buf[bi] <= ' '; bi++);
if (bi < bn) break;
bn = fread(buf, 1, SIZE, stdin);
bi = 0;
}
int sn = 0;
while (bn) {
for (; bi < bn && buf[bi] > ' '; bi++) s[sn++] = buf[bi];
if (bi < bn) break;
bn = fread(buf, 1, SIZE, stdin);
bi = 0;
}
s[sn] = 0;
return sn;
}
bool read(int& x) {
int n = read(str), bf = 0;
if (!n) return 0;
int i = 0; if (str[i] == '-') bf = 1, i++; else if (str[i] == '+') i++;
for (x = 0; i < n; i++) x = x * 10 + str[i] - '0';
if (bf) x = -x;
return 1;
}
bool read(long long& x) {
int n = read(str), bf;
if (!n) return 0;
int i = 0; if (str[i] == '-') bf = -1, i++; else bf = 1;
for (x = 0; i < n; i++) x = x * 10 + str[i] - '0';
if (bf < 0) x = -x;
return 1;
}
void write(int x) {
if (x == 0) obuf[opt++] = '0';
else {
if (x < 0) obuf[opt++] = '-', x = -x;
int sn = 0;
while (x) str[sn++] = x % 10 + '0', x /= 10;
for (int i = sn - 1; i >= 0; i--) obuf[opt++] = str[i];
}
if (opt >= (SIZE >> 1)) {
fwrite(obuf, 1, opt, stdout);
opt = 0;
}
}
void write(long long x) {
if (x == 0) obuf[opt++] = '0';
else {
if (x < 0) obuf[opt++] = '-', x = -x;
int sn = 0;
while (x) str[sn++] = x % 10 + '0', x /= 10;
for (int i = sn - 1; i >= 0; i--) obuf[opt++] = str[i];
}
if (opt >= (SIZE >> 1)) {
fwrite(obuf, 1, opt, stdout);
opt = 0;
}
}
void write(unsigned long long x) {
if (x == 0) obuf[opt++] = '0';
else {
int sn = 0;
while (x) str[sn++] = x % 10 + '0', x /= 10;
for (int i = sn - 1; i >= 0; i--) obuf[opt++] = str[i];
}
if (opt >= (SIZE >> 1)) {
fwrite(obuf, 1, opt, stdout);
opt = 0;
}
}
void write(char x) {
obuf[opt++] = x;
if (opt >= (SIZE >> 1)) {
fwrite(obuf, 1, opt, stdout);
opt = 0;
}
}
void Fflush() { if (opt) fwrite(obuf, 1, opt, stdout); opt = 0;}
};
int n, m, q;
int w[N][N];
int tag[N][N];
int cnt[N * N];
char s[4000000 + 5];
void run() {
FI(n), FI(m), FI(q);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
FI(w[i][j]);
cnt[w[i][j]] = -1;
}
}
while (q--) {
int sx, sy;
FI(sx), FI(sy);
FI(s);
int len = strlen(s);
int L = m + 1, R = 0, D = n + 1, U = 0;
int x = sx, y = sy;
for (int i = 0; i < len; i++) {
L = min(L, x);
R = max(R, x);
D = min(D, y);
U = max(U, y);
if (s[i] == 'L') --x;
if (s[i] == 'R') ++x;
if (s[i] == 'D') --y;
if (s[i] == 'U') ++y;
}
++L, ++D;
assert(D <= U && L <= R);
for (int i = L; i <= R; i++) {
for (int j = D; j <= U; j++) {
tag[i][j] = 0;
}
}
x = sx, y = sy;
for (int i = 0; i < len; i++) {
if (s[i] == 'R') {
++x;
tag[x][y + 1] = 1;
}
if (s[i] == 'L') {
tag[x][y + 1] = 1;
--x;
}
if (s[i] == 'D') {
--y;
}
if (s[i] == 'U') {
++y;
}
}
int ans = 0;
for (int i = L; i <= R; i++) {
int op = 0;
for (int j = D; j <= U; j++) {
op ^= tag[i][j];
if (op) {
if (cnt[w[i][j]] != q) {
cnt[w[i][j]] = q;
++ans;
}
}
}
}
FO(ans), FO('
');
}
}
int main() {
int T; cin >> T; while(T--)
run();
Flush;
return 0;
}
J. Lead of Wisdom
直接爆搜。
Code
// Author : heyuhhh
// Created Time : 2020/07/23 12:57:36
#include<bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 50 + 5;
#define FI(n) FastIO::read(n)
#define FO(n) FastIO::write(n)
#define Flush FastIO::Fflush()
namespace FastIO {
const int SIZE = 1 << 16;
char buf[SIZE], obuf[SIZE], str[60];
int bi = SIZE, bn = SIZE, opt;
double D[] = {0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001, 0.00000001, 0.000000001, 0.0000000001};
int read(char *s) {
while (bn) {
for (; bi < bn && buf[bi] <= ' '; bi++);
if (bi < bn) break;
bn = fread(buf, 1, SIZE, stdin);
bi = 0;
}
int sn = 0;
while (bn) {
for (; bi < bn && buf[bi] > ' '; bi++) s[sn++] = buf[bi];
if (bi < bn) break;
bn = fread(buf, 1, SIZE, stdin);
bi = 0;
}
s[sn] = 0;
return sn;
}
bool read(int& x) {
int n = read(str), bf = 0;
if (!n) return 0;
int i = 0; if (str[i] == '-') bf = 1, i++; else if (str[i] == '+') i++;
for (x = 0; i < n; i++) x = x * 10 + str[i] - '0';
if (bf) x = -x;
return 1;
}
bool read(long long& x) {
int n = read(str), bf;
if (!n) return 0;
int i = 0; if (str[i] == '-') bf = -1, i++; else bf = 1;
for (x = 0; i < n; i++) x = x * 10 + str[i] - '0';
if (bf < 0) x = -x;
return 1;
}
void write(int x) {
if (x == 0) obuf[opt++] = '0';
else {
if (x < 0) obuf[opt++] = '-', x = -x;
int sn = 0;
while (x) str[sn++] = x % 10 + '0', x /= 10;
for (int i = sn - 1; i >= 0; i--) obuf[opt++] = str[i];
}
if (opt >= (SIZE >> 1)) {
fwrite(obuf, 1, opt, stdout);
opt = 0;
}
}
void write(long long x) {
if (x == 0) obuf[opt++] = '0';
else {
if (x < 0) obuf[opt++] = '-', x = -x;
int sn = 0;
while (x) str[sn++] = x % 10 + '0', x /= 10;
for (int i = sn - 1; i >= 0; i--) obuf[opt++] = str[i];
}
if (opt >= (SIZE >> 1)) {
fwrite(obuf, 1, opt, stdout);
opt = 0;
}
}
void write(unsigned long long x) {
if (x == 0) obuf[opt++] = '0';
else {
int sn = 0;
while (x) str[sn++] = x % 10 + '0', x /= 10;
for (int i = sn - 1; i >= 0; i--) obuf[opt++] = str[i];
}
if (opt >= (SIZE >> 1)) {
fwrite(obuf, 1, opt, stdout);
opt = 0;
}
}
void write(char x) {
obuf[opt++] = x;
if (opt >= (SIZE >> 1)) {
fwrite(obuf, 1, opt, stdout);
opt = 0;
}
}
void Fflush() { if (opt) fwrite(obuf, 1, opt, stdout); opt = 0;}
};
int n, k;
int a[N], b[N], c[N], d[N];
int type[N][N];
int num[N];
int sa, sb, sc, sd;
ll ans;
void dfs(int cur) {
if (cur == 0) {
ans = max(ans, 1ll * sa * sb * sc * sd);
return;
}
int prea, preb, prec, pred;
prea = preb = prec = pred = -1;
if (num[cur]) for (register int i = 1; i <= num[cur]; ++i) {
int id = type[cur][i];
sa += a[id], sb += b[id], sc += c[id], sd += d[id];
if (prea == -1) {
prea = sa;
preb = sb;
prec = sc;
pred = sd;
dfs(cur - 1);
} else {
if (sa <= prea && sb <= preb && sc <= prec && sd <= pred) {
} else {
dfs(cur - 1);
}
prea = min(prea, sa);
preb = min(preb, sb);
prec = min(prec, sc);
pred = min(pred, sd);
}
sa -= a[id], sb -= b[id], sc -= c[id], sd -= d[id];
} else {
dfs(cur - 1);
}
}
void run() {
FI(n), FI(k);
for (register int i = 1; i <= k; ++i) {
num[i] = 0;
}
ans = 0;
for (register int i = 1; i <= n; ++i) {
int t; FI(t);
FI(a[i]), FI(b[i]), FI(c[i]), FI(d[i]);
type[t][++num[t]] = i;
}
sa = sb = sc = sd = 100;
dfs(k);
FO(ans), FO('
');
}
int main() {
#ifdef Local
freopen("input.in", "r", stdin);
#endif
int T; FI(T); while(T--)
run();
Flush;
return 0;
}
L. String Distance
题意:
给出两个字符串(S,T),长度分别为(n,m(nleq 10^5,mleq 20)),现在每一次操作都可以在任意一个位置插入或者删除一个字符。
之后会给出若干组询问,每次询问区间([l_i,r_i]),然后需要回答使得(s)串这一个子串和(t)串相等的最小操作次数为多少。
思路:
其实就是要我们求(s_{l,...,r})和(t)串的lcs,那么答案就为(r-l+1+m-2cdot lcs)。
那么正常的做法应该为(dp[i][j]):(s)串匹配到了(i),(t)串匹配到了(j)的lcs为多少,但显然这个状态我们不好存储,时间复杂度也会爆炸。
注意到其实我们只需要check长度为(k)的lcs是否存在,所以换一下dp的方式,(dp[i][j])表示(t)串考虑了前(i)位,长度为(j)的lcs匹配到了(s)串的哪个位置(就相当于换一下状态)。那么之后就是一个(O(m^2))的(dp)了。所以总的时间复杂度为(O(nm^2))。
细节见代码:
Code
// Author : heyuhhh
// Created Time : 2020/07/23 20:36:09
#include<bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5, M = 20 + 5;
char s[N], t[M];
int n, m;
int nxt[N][26];
int dp[M][M];
void run() {
cin >> (s + 1) >> (t + 1);
n = strlen(s + 1);
m = strlen(t + 1);
for (int i = 0; i < 26; i++) {
nxt[n][i] = n + 1;
}
for (int i = n - 1; i >= 0; i--) {
for (int j = 0; j < 26; j++) {
nxt[i][j] = nxt[i + 1][j];
}
nxt[i][s[i + 1] - 'a'] = i + 1;
}
int q;
cin >> q;
while (q--) {
int l, r; cin >> l >> r;
memset(dp, -1, sizeof(dp));
dp[0][0] = l - 1;
for (int i = 0; i < m; i++) {
for (int j = 0; j <= i; j++) {
if (dp[i][j] >= 0 && dp[i][j] <= r) {
int pos = dp[i][j];
int go = nxt[pos][t[i + 1] - 'a'];
if (dp[i + 1][j + 1] == -1) {
dp[i + 1][j + 1] = go;
} else {
dp[i + 1][j + 1] = min(dp[i + 1][j + 1], go);
}
if (dp[i + 1][j] == -1) {
dp[i + 1][j] = dp[i][j];
} else {
dp[i + 1][j] = min(dp[i + 1][j], dp[i][j]);
}
}
}
}
int ans = r - l + 1 + m;
for (int i = m; i >= 0; i--) {
if (dp[m][i] >= l && dp[m][i] <= r) {
ans -= 2 * i;
break;
}
}
cout << ans << '
';
}
}
int main() {
#ifdef Local
freopen("input.in", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
int T; cin >> T; while(T--)
run();
return 0;
}