2020 Multi-University Training Contest 2

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<<'\n';
    }
}

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] << " \n"[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_1\cdot F_1+a_2\cdot F_2+\cdots+a_n\cdot F_n,a_i\in\{0,1\}\)
现有\(A\cdot 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('\n');
                    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('\n');
}
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('\n');
    }
}
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('\n');
}
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(n\leq 10^5,m\leq 20)\),现在每一次操作都可以在任意一个位置插入或者删除一个字符。
之后会给出若干组询问,每次询问区间\([l_i,r_i]\),然后需要回答使得\(s\)串这一个子串和\(t\)串相等的最小操作次数为多少。

思路:
其实就是要我们求\(s_{l,...,r}\)\(t\)串的lcs,那么答案就为\(r-l+1+m-2\cdot 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 << '\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;
}
posted @ 2020-07-25 11:04  heyuhhh  阅读(263)  评论(0编辑  收藏  举报