[POI2011]LIZ-Lollipop 题解

[POI2011]LIZ-Lollipop

题目描述

Byteasar runs a confectionery in Byteburg.

Strawberry-vanilla flavoured lollipops are the favourite of local children.

These lollipops are composed of multiple segments of the same length, each segment of either strawberry or vanilla flavour.

The price of the lollipop is the sum of the values of its segments, where a vanilla segment costs one bythaler, while a strawberry segments costs two.

Fig. 1: An exemplary lollipop of five segments, three strawberry flavoured and two vanilla, alternately.

The price of this lollipop is 8 8 8 bythalers.

Currently Byteasar is left with only one lollipop, though possibly very long.

As a salesman, he knows only too well that probably no one will want to buy the whole lollipop. For this reason he thinks of breaking the lollipop at the joints of the segments in order to get a shorter lollipop. Each fragment for sale, of course, must stay in one piece.

Byteasar vast experience of a salesman, as well as his understanding of children psychology, tell him that his young customers will most likely want to spend all their money on a single lollipop. With this in mind, he wonders for which values of k k k the lollipop he has can be broken down in such a way that as a result one would get, among other pieces, a lollipop worth exactly k k k bythalers.

Naturally, he is interested in the way of breaking the lollipop as well.

As this task overwhelms him, he asks you for help.

给一个只有1和2的序列,每次询问有没有一个子串的和为x

输入格式

In the first line of the standard input there are two integers n n n and m m m ( 1 ≤ n , m ≤ 1   000   000 1\le n,m \le 1\ 000\ 000 1n,m1 000 000), separated by a single space.

These denote, respectively, the number of segments of the last lollipop left in store, and the number of values of k k k to consider.

The lollipop’s segments are numbered from 1 to n n n.

The second line gives an n n n-letter description of the lollipop, consisting of letters T and W, where T denotes a strawberry flavoured segment, while W - vanilla flavoured;the i i i-th of these letters specifies the flavour of the i i i-th segment.

In the following m m m lines successive values of k k k( 1 ≤ k ≤ 2   000   000 1\le k\le 2\ 000\ 000 1k2 000 000) to consider are given, one per line.

输出格式

Your program should print out exactly m m m lines, giving, one per line, the results for successive values of k k k, to the standard output.

If for a given value of k k k it is impossible to break the lollipop in such a way that there is a contiguous fragment worth exactly k k k bythalers, then the word NIE (no in Polish) should be printed. Otherwise, two integers l l l and r r r ( 1 ≤ l ≤ r ≤ n 1\le l\le r\le n 1lrn), separated by single spaces, should be printed, such that the fragment of the lollipop composed of the segments numbered from l l l to r r r inclusively is worth exactly k k k bythalers. If there are multiple such pairs, your program is free to choose one arbitrarily.

样例 #1

样例输入 #1

5 3
TWTWT
5
1
7

样例输出 #1

1 3
2 2
NIE

提示

给一个只有1和2的序列,每次询问有没有一个子串的和为x

SPJ对于格式的要求较为严格。对于每个询问后,应紧跟一个换行符。在最后一次输出你的答案以及一个换行符后不应有任何输出。

由zhouyonglong提供SPJ

题解

首先因为元素只能为1/2,所以我们可以思考如何利用上这个性质,可以发现如下重要性质

若存在一个和为 k k k的区间,则一定有一个和为 k − 2 k-2 k2的区间

证明:设这个区间为 [ l , r ] [l,r] [l,r],则对 l , r l,r l,r两个位置上的权值分类讨论,若二者其中至少有一个权值为2,那么就把那个端点删去就得到了一个和为 k − 2 k-2 k2的区间,而若二者的权值都为1,从两端删去即可

那么我们就可以考虑将一个足够大的区间往回缩,不断递归,可以得到与此区间的和的奇偶性相同且小于的所有值所对区间

到了这里,做法就很显然了,先找到最大奇数段和最大偶数段,然后递归预处理每个值的答案区间即可,复杂度只有 O ( N ) O(N) O(N)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define N 2000050
#define scanf scanf_s
struct node {
	int l, r;
}ans[N];
int val[N], n, m, q, s1[N], s2[N], pos1, pos2;
void dfs(int l, int r, int k) {
	if (ans[k].l)return;
	if (l > r)return;
	ans[k] = { l,r };
	if (val[l] == 2) {
		dfs(l + 1, r, k - 2);
	}
	else if (val[r] == 2) {
		dfs(l, r - 1, k - 2);
	}
	else dfs(l + 1, r - 1, k - 2);
}
void init() {
	memset(ans, 0, sizeof ans);
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) {
		char x;
		cin >> x;
		if (x == 'T')val[i] = 2;
		else val[i] = 1;
	}
	for (int i = 1; i <= n; i++)s1[i] = s1[i - 1] + val[i];
	for (int i = n; i >= 1; --i)s2[i] = s2[i + 1] + val[i];
	for (int i = 1; i <= n; i++)if (val[i] == 1) { pos1 = i + 1; break; }
	for (int i = n; i > 0; --i)if (val[i] == 1) { pos2 = i - 1; break; }
	if (s2[pos1] > s1[pos2]) { dfs(pos1, n, s2[pos1]); }
	else { dfs(1, pos2, s1[pos2]); }
	dfs(1, n, s1[n]);
}
int main() {
	init();
	while (m--) {
		int k;
		scanf("%d", &k);
		if (ans[k].l == 0)puts("NIE");
		else printf("%d %d\n", ans[k].l, ans[k].r);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值