【CF1774C】Ice and Fire(构造,DP)
【题目描述】
有nnn个人,第iii个人的温度为iii。
环境类型为000或111,若环境为000,则温度低的人胜利,若环境为111,则温度高的人胜利,n−1n-1n−1个环境类型组成一个长为n−1n-1n−1的二进制串sss。
若xxx个人参与游戏,则共有x−1x-1x−1场战斗,环境类型即为sss的前x−1x-1x−1个元素。在有不少于222个人时,任选222个人进行战斗,其中第iii场战斗的环境类型为sis_isi。
对于任意一个从222到nnn的xxx,如果所有温度不超过xxx的人都参与比赛,有多少人有机会获胜(活到最后)?
【输入格式】
第一行一个整数t(1≤t≤103)t(1\\le t\\le 10^3)t(1≤t≤103),表示测试样例的数量。
对于每组测试样例第一行输入一个整数n(2≤n≤2×105)n(2\\le n\\le 2\\times 10^5)n(2≤n≤2×105),表示玩家个数。
第二行输入一个长度为n−1n-1n−1的字符串sss。
数据保证每组测试用例中的nnn的和不超过3×1053\\times 10^53×105。
【输出格式】
对于每组测试用例,输出一行共n−1n-1n−1个整数,即对于从222到nnn的每一个xxx,有多少人有机会获胜。
【输入样例】
2
4
001
4
101
【输出样例】
1 1 3
1 2 3
【说明/提示】
In the first test case, for x=2x=2x=2 and x=3x=3x=3, only the player whose temperature value is 111 can be the winner. For x=4x=4x=4 , the player whose temperature value is 2,3,42,3,42,3,4 can be the winner.
【分析】
假设最后一场的环境为111,即温度大的人赢,那么温度为111的人即使活到了最后一场也必输。
同理,如果最后kkk场的环境都为111,那么有k(1∼k)k(1\\sim k)k(1∼k)个人一定没机会赢,另外的x−kx-kx−k名选手都有机会赢,因为只有温度大于等于k+1k+1k+1的人才可能连续战胜温度为1∼k1\\sim k1∼k的人活到最后。
那么如何保证k+1∼xk+1\\sim xk+1∼x名选手都有机会活到最后kkk场呢?假设要使选手i(k+1≤i≤x)i(k+1\\le i\\le x)i(k+1≤i≤x)活到最后kkk场,只需要先让剩下的在k+1∼xk+1\\sim xk+1∼x中的选手互相对战,由于第k−1k-1k−1场环境一定为000,那么让剩下的另一名选手jjj和1∼k1\\sim k1∼k中的选手打,被淘汰,那么iii就活到了最后kkk场。
反之如果最后kkk场的环境都为000也同样可以证明有机会赢的人数为x−kx-kx−k。
【代码】
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;int main()
{int T, n;string s;cin >> T;while (T--){cin >> n >> s;cout << 1 << ' ';for (int i = 1, k = 1; i < s.size(); i++) // k表示最长相同后缀的长度{if (s[i] == s[i - 1]) k++;else k = 1;cout << i + 2 - k << ' '; // 第1 ~ i + 2名选手参赛}cout << endl;}return 0;
}