教育コードフォースラウンド103(Div。2の評価)D。旅(dp)

タイトル説明

0からnまでの番号が付けられたn + 1の都市があります。n本の道路がこれらの都市を接続し、i番目の道路が都市i-1とiを接続します(i∈[1、n])。
各道路には方向があります。方向は、各文字がLまたはRになるようにn文字の文字列で指定されます。i番目の文字がLの場合、i番目の道路が最初に都市iから都市i-1に向かうことを意味します。それ以外の場合は、都市i-1から都市iに移動します。
旅行者は、この国のできるだけ多くの都市を訪問したいと考えています。最初に、彼らは旅を始めるためにいくつかの都市を選びます。旅行者は毎日、現在いる都市から隣接する都市に道路の1つを使用して移動する必要があり、同じ方向に向けられている場合にのみ道路に沿って移動できます。私。たとえば、道路が都市iから都市i ​​+ 1に向けられている場合、iからi + 1に移動することはできますが、i +1からiに移動することはできません。旅行者が隣の都市に移動した後、すべての道路は反対方向に方向を変えます。旅行者が現在の都市から近隣の都市に行けない場合、旅行は終了します。旅行者が望むときはいつでも旅を終えることも可能です。
旅行者の目標は、できるだけ多くの異なる都市を訪問することです(都市を複数回訪問できますが、最初の訪問のみがカウントされます)。都市iごとに、旅行者が都市iで開始した場合に、1回の旅行で訪問できるさまざまな都市の最大数を計算します。

入力

最初の行には、1つの整数t(1≤t≤104)—テストケースの数が含まれています。
各テストケースは2行で構成されています。最初の行には1つの整数n(1≤n≤3・105)が含まれています。2行目には、正確にn文字で構成される文字列sが含まれ、各文字はLまたはRのいずれか
です。すべてのテストケースのnの合計が3・105を超えないことが保証されます。

出力

テストケースごとに、n +1個の整数を出力します。i番目の整数は、この旅がi番目の都市で始まる場合、旅行者が1回の旅で訪れることができるさまざまな都市の最大数と等しくなければなりません。

入力
2
6
LRRRLL
3
LRLの
出力
1 3 2 3 1 2 3
1 4 1 4

一般的なアイデア

:指定されたNエッジは、N + 1個の異なる町があり、各エッジは方向を有する
L手段I-1〜Iからエッジが存在すること、および
ことをR手段エッジが存在するI + 1〜Iからは。
観光客が行きますそれぞれから町iから始まり、次の町に到着するたびに、すべてのエッジが反転し、LがRになり、RがLになります。各町について、旅行者が到達できる町の最大数はいくつですか。

トピック分析

それぞれの答えについて、それを3つの部分に分けることができます:
1)開始都市自体:1。

2)各ステップですべてのエッジが反転するため、左のpre [i]に移動して到達できる都市の数pre[i]=从i开始向左LRLR序列的最大长度
pre [i]がどのように取得されるかを考えることができます。実際、これは単純なdpです。s
[i] = 'L'およびs [i-1] = 'R'のpre[i]=pre[i-2]+2;
場合、s [i] = 'の場合L '、それpre[i]=1;
以外の場合、pre[i]=0;

3)右に行くことで到達できる都市の数はsuf [i]であり、同じことが当てはまりますsuf[i]=从i+1开始向右RLRL序列的最大长度
suf [i]を解決するプロセスは、pre [i]を解決するという考え方と同じなので、ここではこれ以上説明しません。

コードは以下のように表示されます
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <bitset>
#include <algorithm>
#define LL long long
#define PII pair<int,int>
#define x first
#define y second
using namespace std;
const int N=3e5+5;
char s[N];
int pre[N],suf[N];
int main()
{
    
    
    int t;
	scanf("%d",&t);
	while(t--)
	{
    
    
		int n;
		scanf("%d",&n);
		scanf("%s",s+1);
		for(int i=0;i<=n+1;i++) pre[i]=suf[i]=0;		//清空pre[]和suf[]
		for(int i=1;i<=n;i++)				//求出pre[]
		{
    
    
			if(s[i]=='L'&&s[i-1]=='R') pre[i]=pre[i-2]+2;
			else if(s[i]=='L') pre[i]=1;
		}
		for(int i=n-1;i>=0;i--)				//求出suf[]
		{
    
    
			if(s[i+1]=='R'&&s[i+2]=='L') suf[i]=suf[i+2]+2;
			else if(s[i+1]=='R') suf[i]=1;
		}
		for(int i=0;i<=n;i++)				//第i个城市能到多少点即为三部分内容的相加
			printf("%d ",pre[i]+suf[i]+1);
		puts("");
	}
    return 0;
}

おすすめ

転載: blog.csdn.net/li_wen_zhuo/article/details/113432840