2024CSP前集训10.9

不想学东西了,,,


T4 25分,卡点没交上。

T1

普及题,之前还做过,没啥好说的。

T2

95

kmp 不对,挂了 5 分。

莫队奇偶性优化还是要加的。

\(s_{i,\dots,n}\) 跑 kmp,也就是跑了 \(n\) 遍,答案是:

	while (m--) {
		int l = read(), r = read();
		int res = 0;
		for (int i = l; i <= r; i++)
			for (int j = i; j <= r; j++)
				if (p[i][j])
					if (vs[j][p[i][j]] == 0)
						res++, vs[j][p[i][j]] = 1;
		cout << (r - l + 1) * (r - l + 2) / 2 - res << '\n';
		memset(vs, 0, sizeof(vs));
	}
// 这是暴力

统计有多少个重复的串,再用总共的减去。
如果某个位置的 \(border\) 不为 \(0\),就说明前面出现了这个串,但是要注意每个位置同样长度的串只减一次。

改成莫队加减都很方便。

复杂度 \(O(n^2\sqrt q)\),但跑的挺快。

不会正解。

#include <bits/stdc++.h>

using namespace std;

int read() {
	int x;
	cin >> x;
	return x;
}

const int maxN = 3e3 + 7, maxM = 2e4 + 7;

int n, m;

string s;

int p[maxN][maxN];

int vs[maxN][maxN];

int pos[maxN], len;

struct ques {
	int l, r, id;
} q[maxM];
int ans[maxM];

int l = 1, r;
int res;

void addr() {
	for (int i = l; i <= r; i++)
		if (p[i][r]) {
			if (!vs[r][p[i][r]])
				res++;
			vs[r][p[i][r]]++;
		}
}
void addl() {
	for (int i = l; i <= r; i++)
		if (p[l][i]) {
			if (!vs[i][p[l][i]])
				res++;
			vs[i][p[l][i]]++;
		}
}
void dell() {
	for (int i = l; i <= r; i++)
		if (p[l][i]) {
			vs[i][p[l][i]]--;
			if (!vs[i][p[l][i]])
				res--;
		}
}
void delr() {
	for (int i = l; i <= r; i++)
		if (p[i][r]) {
			vs[r][p[i][r]]--;
			if (!vs[r][p[i][r]])
				res--;
		}
}

int main() {
	freopen("substring.in", "r", stdin);
	freopen("substring.out", "w", stdout);

	// ios::sync_with_stdio(false), cin.tie(nullptr);

	n = read(), m = read();
	cin >> s;
	s = '@' + s;
	for (int st = 1; st <= n; st++) {
		string tmp;
		for (int i = st; i <= n; i++)
			tmp += s[i];
		int *br = p[st];
		br[0] = 0;
		for (int i = 1; i < n - st + 1; i++) {
			int j = br[i - 1];
			while (j > 0 && tmp[i] != tmp[j])
				j = br[j - 1];
			if (tmp[i] == tmp[j])
				br[i] = j + 1;
			else
				br[i] = 0;
		}
		for (int i = n - st, j = n; i >= 0; i--, j--)
			br[j] = br[i], br[i] = 0;
	}

	len = max(n / sqrt(m), 1.0);
	for (int i = 1; i <= n; i++)
		pos[i] = (i - 1) / len + 1;

	for (int i = 1; i <= m; i++)
		q[i].l = read(), q[i].r = read(), q[i].id = i;
	sort(q + 1, q + m + 1, [](ques A, ques B) {
		if (pos[A.l] == pos[B.l])
			return (pos[A.l] & 1) ? A.r < B.r : A.r > B.r;
		return A.l < B.l;
	});

	for (int i = 1; i <= m; i++) {
		while (r < q[i].r)
			r++, addr();
		while (q[i].l < l)
			l--, addl();
		while (l < q[i].l)
			dell(), l++;
		while (q[i].r < r)
			delr(), r--;
		int len = q[i].r - q[i].l + 1;
		ans[q[i].id] = len * (len + 1) / 2 - res;
	}

	for (int i = 1; i <= m; i++)
		cout << ans[i] << '\n';
}

T3

#include <bits/stdc++.h>

using namespace std;

using ubt = long long;

int read() {
    int s = 0, w = 1;
    char c = getchar();
    while (!isdigit(c)) {
        if (c == '-')
            w = -w;
        c = getchar();
    }
    while (isdigit(c)) {
        s = s * 10 + c - 48;
        c = getchar();
    }
    return w * s;
}
void pr(ubt x) {
    if (x < 0)
        putchar('-'), x = -x;
    if (x > 9)
        pr(x / 10);
    putchar(x % 10 + 48);
}
#define end_ putchar('\n')
#define spc_ putchar(' ')


const int maxN = 4e5 + 7;

struct trie {
    int n;
    int ch[maxN][26];
    ubt cnt[26];
    void insert(string s, bool ty) {
        int u = 0, len = s.length();
        if (!ty) {
            for (int i = 0; i < len; i++) {
                int o = s[i] - 'a';
                if (!ch[u][o])
                    ch[u][o] = ++n;
                u = ch[u][o];
            }
        }
        else {
            for (int i = len - 1; ~i; i--) {
                int o = s[i] - 'a';
                if (!ch[u][o])
                    ch[u][o] = ++n, cnt[o]++;
                u = ch[u][o];
            }
        }
    }
} t1, t2;

int n;
ubt ans;

bool ok[26], flag[26];

int main() {
    freopen("magic.in", "r", stdin);
    freopen("magic.out", "w", stdout);

    n = read();
    for (int i = 1; i <= n; i++) {
        string s;
        cin >> s;
        t1.insert(s, false), t2.insert(s, true);
        int len = s.length();
        ok[s[len - 1] - 'a'] = true;
        if (len == 1 && !flag[s[0] - 'a'])
            ans++, flag[s[0] - 'a'] = true;
    }
    for (int u = 1; u <= t1.n; u++)
        for (int o = 0; o < 26; o++)
            if (!t1.ch[u][o])
                ans += t2.cnt[o];
            else
                ans += ok[o];
    pr(ans), end_;
}
posted @ 2024-10-09 19:20  ccxswl  阅读(16)  评论(2编辑  收藏  举报