QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#58032#4844. Positive StringMIT01#ML 0ms0kbC++174.0kb2022-10-24 11:23:462022-10-24 11:23:47

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2022-10-24 11:23:47]
  • 评测
  • 测评结果:ML
  • 用时:0ms
  • 内存:0kb
  • [2022-10-24 11:23:46]
  • 提交

answer

#include <bits/stdc++.h>

using namespace std;

#define REP(i, a, b) for (int i = (a), i##_end_ = (b); i < i##_end_; ++i)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define mp make_pair
#define x first
#define y second
#define pb emplace_back
#define SZ(x) (int((x).size()))
#define ALL(x) (x).begin(), (x).end()

template<typename T> inline bool chkmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }

typedef long long LL;

const int oo = 0x3f3f3f3f;

const int maxn = 200010;

int n;
int s[maxn * 2 + 5];

int tot = 0;
map<int, int> go[maxn * 4 + 5];
int fa[maxn * 4 + 5];
int Max[maxn * 4 + 5];

int rt = 0;

inline int add(int p, int w)
{
	if (go[p][w] && Max[go[p][w]] == Max[p] + 1) return go[p][w];
	int np = tot++;
	fa[np] = -1;
	Max[np] = Max[p] + 1;
	while (p != -1 && !go[p][w]) go[p][w] = np, p = fa[p];
	if (p == -1) fa[np] = rt;
	else
	{
		int q = go[p][w];
		if (Max[q] == Max[p] + 1) fa[np] = q;
		else
		{
			int nq = tot++;
			fa[nq] = -1;
			Max[nq] = Max[p] + 1;
			go[nq] = go[q];
			fa[nq] = fa[q];
			fa[np] = fa[q] = nq;
			while (p != -1 && go[p][w] == q)
			{
				go[p][w] = nq;
				p = fa[p];
			}
		}
	}
	return np;
}

struct node
{
	node *c[2], *p;
	LL sum;
	int cnt;
	int w;
	int sumw;
	int label;

	node(): p(NULL), sum(0), cnt(0), w(0), sumw(0), label(0)
	{
		memset(c, 0, sizeof c);
	}

	void update()
	{
		sumw = w;
		sum = (LL)cnt * w;
		REP(i, 0, 2) if (c[i])
		{
			sumw += c[i]->sumw;
			sum += c[i]->sum;
		}
	}

	void flag_label(int x)
	{
		cnt += x;
		label += x;
		sum += (LL)x * sumw;
	}

	void push_down()
	{
		if (label)
		{
			REP(i, 0, 2)
				if (c[i])
				{
					c[i]->flag_label(label);
				}
			label = 0;
		}
	}

	int get_pos()
	{
		if (!this || !p) return 2;
		REP(i, 0, 2) if (p->c[i] == this) return i;
		return 2;
	}

	bool is_root()
	{
		return get_pos() >= 2;
	}

	void setc(node *u, int v)
	{
		if (this && v < 2) c[v] = u;
		if (u) u->p = this;
	}

	void rotate()
	{
		node *tmp = this->p;
		bool mark = get_pos();
		tmp->p->setc(this, tmp->get_pos());
		tmp->setc(c[mark ^ 1], mark);
		setc(tmp, mark ^ 1);
		tmp->update();
	}

	void relax()
	{
		static node *tmp[maxn + 5];
		int top = 0;
		node *u = this;
		while (!u->is_root()) tmp[top++] = u, u = u->p;
		u->push_down();
		while (top)
		{
			tmp[--top]->push_down();
		}
	}

	void splay()
	{
		relax();
		for ( ; !is_root(); rotate())
			if (!p->is_root()) ((p->p->c[0] == p) == (p->c[0] == this) ? p : this)->rotate();
		update();
	}

	node *access()
	{
		node *u = this, *v = NULL;
		for ( ; u; v = u, u = u->p)
		{
			u->splay();
			u->setc(v, 1);
			u->update();
		}
		splay();
		return v;
	}

};

int where[maxn * 2 + 5];
node nd[27][maxn * 4 + 5];

inline LL query(int x)
{
	int tmp = where[x];
	LL ret = 0;
	for (int i = s[x]; i > 0; i -= i & -i)
	{
		nd[i][tmp].access();
		ret += nd[i][tmp].sum;
	}
	return ret;
}

inline void add(int x)
{
	int tmp = where[x];
	for (int i = s[x] + 1; i <= 26; i += i & -i)
	{
		nd[i][tmp].access();
		nd[i][tmp].flag_label(1);
	}
}

int main()
{
#ifdef LOCAL
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	static char ss[maxn + 5];
	scanf("%s", ss);
	n = strlen(ss);
	REP(i, 0, n) s[i] = ss[i] - 'a';
	s[n] = 26;
	REP(i, 0, n) s[2 * n - i] = ss[i] - 'a';
	n = 2 * n + 1;

	tot = 1;
	fa[0] = -1;
	int cur = 0;
	REP(i, 0, n) 
	{
		where[i] = cur;
		cur = add(cur, s[i]);
	}
	where[n] = cur;

//	REP(i, 0, tot) if (~fa[i]) children[fa[i]].pb(i);
//	dfs(0)

	REP(j, 1, 27)
	{
		REP(i, 0, tot)
		{
			if (~fa[i]) nd[j][i].p = nd[j] + fa[i];
			nd[j][i].w = (Max[i] + 1) - (~fa[i] ? (Max[fa[i]] + 1) : 0);
			nd[j][i].update();
		}
	}

	LL ans = 0;
	int j = n >> 1;
	for (int i = (n >> 1) - 1; i >= 0; --i)
	{
		ans += query(i);
		++j;
		if (j < n)
		{
			add(j);
		}
	}
	printf("%lld\n", ans);
	return 0;
}

详细

Test #1:

score: 0
Memory Limit Exceeded

input:

jjikkollp

output:


result: