[洛谷] P3514 [POI2011]LIZ-Lollipop

Description

Link

Solution

很难想到啊。。

对于一个和为X的串S,注意到我们总能构造出一个长度更小的S满足X=X2

即,设S=s[lr],若s[l]==s[r]==W,就l++,r

否则设s[l]==T,直接l++即可。

所以按照子串和的奇偶性分类,依次构造就可以了。问题是如何找出某一奇偶性的S中,X最大,且|S|尽量大的初始串。

其实,这个串一定是s[1i]或者s[in]

证明:如果S=s[lr](l1,rn),若s[l1]==T[r+1]==T,总可以使lr++,从而|S|变大且不会影响奇偶性。

如果x>p[x%2]就输出NIE

Code

#include <bits/stdc++.h>

using namespace std;

int n, m, l1, r1, l2, r2, s[1000005], p[2], rl[2000005], rr[2000005];

char ch[1000005];

int read()
{
	int x = 0, fl = 1; char ch = getchar();
	while (ch < '0' || ch > '9') { if (ch == '-') fl = -1; ch = getchar();}
	while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + ch - '0'; ch = getchar();}
	return x * fl;
}

void check(int l, int r)
{
	int now = s[r] - s[l - 1];
	if (now >= p[now % 2])
	{
		p[now % 2] = now;
		if (now % 2 && r - l > r1 - l1) {l1 = l, r1 = r;}
		if (now % 2 == 0 && r - l > r2 - l2) {l2 = l, r2 = r;}
	}
	return;
}

int main()
{
	n = read(), m = read();
	scanf("%s", ch + 1);
	for (int i = 1; i <= n; i ++ )
		s[i] = s[i - 1] + ((ch[i] == 'T') ? 2 : 1);
	for (int i = 1; i <= n; i ++ ) check(1, i);
	for (int i = 1; i <= n; i ++ ) check(i, n);
	int now = p[1];
	while (now >= 1)
	{
		rl[now] = l1, rr[now] = r1;
		if (ch[l1] == 'W' && ch[r1] == 'W') {l1 ++ , r1 -- ;}
		else
		{
			if (ch[l1] == 'T') l1 ++ ;
			else r1 -- ;
		}
		now -= 2;
	}
	now = p[0];
	while (now >= 2)
	{
		rl[now] = l2, rr[now] = r2;
		if (ch[l2] == 'W' && ch[r2] == 'W') {l2 ++ , r2 -- ;}
		else
		{
			if (ch[l2] == 'T') l2 ++ ;
			else r2 -- ;
		}
		now -= 2;
	}
	while (m -- )
	{
		int x = read();
		if (x > p[x % 2])
		{
			puts("NIE");
			continue;
		}
		printf("%d %d\n", rl[x], rr[x]);
	}
	return 0;
}
posted @   andysj  阅读(71)  评论(2编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示