Repository: online-judge-tools/template-generator (language: python)

Issue:
some types are broken in generated C++ code
入力部分が `string N;` になってる

``` c++
$ oj-template https://atcoder.jp/contests/abc162/tasks/abc162_d
INFO:onlinejudge._implementation.logging:[x] load cookie from: /home/user/.local/share/online-judge-tools/cookie.jar
INFO:onlinejudge._implementation.logging:[x] problem recognized: AtCoderProblem.from_url('https://atcoder.jp/contests/abc162/tasks/abc162_d'): https://atcoder.jp/contests/abc162/tasks/abc162_d
INFO:onlinejudge._implementation.logging:[x] GET: https://atcoder.jp/contests/abc162/tasks/abc162_d
INFO:onlinejudge._implementation.logging:[x] 200 OK
INFO:onlinejudge._implementation.logging:[x] save cookie to: /home/user/.local/share/online-judge-tools/cookie.jar
ERROR:onlinejudge_template.analyzer.combined:output analyzer failed: 
#include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; (i) < (int)(n); ++ (i))
#define REP3(i, m, n) for (int i = (m); (i) < (int)(n); ++ (i))
#define REP_R(i, n) for (int i = (int)(n) - 1; (i) >= 0; -- (i))
#define REP3R(i, m, n) for (int i = (int)(n) - 1; (i) >= (int)(m); -- (i))
#define ALL(x) ::std::begin(x), ::std::end(x)
using namespace std;


int64_t solve(int64_t N, string S) {
    // TODO: edit here
}

// generated by online-judge-template-generator v4.1.0 (https://github.com/kmyk/online-judge-template-generator)
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    constexpr char endl = '\n';
    string N;
    string S;
    cin >> N >> S;
    auto ans = solve(N, S);
    cout << ans << endl;
    return 0;
}
```


Discussion / hints:
At the version `v4.7.1`, the types are sometimes broken. This is not fixed yet.

Fix patch:
diff --git a/onlinejudge_prepare/main.py b/onlinejudge_prepare/main.py
index b9685fb..d480896 100644
--- a/onlinejudge_prepare/main.py
+++ b/onlinejudge_prepare/main.py
@@ -75,6 +75,8 @@ def get_directory(*, problem: onlinejudge.type.Problem, contest: Optional[online
 
 
 def prepare_problem(problem: onlinejudge.type.Problem, *, contest: Optional[onlinejudge.type.Contest] = None, config: Dict[str, Any], session: requests.Session) -> None:
+    logger.info('prepare the problem: %s', problem.get_url())
+
     table = config.get('templates')
     if table is None:
         table = {
@@ -97,14 +99,17 @@ def prepare_problem(problem: onlinejudge.type.Problem, *, contest: Optional[onli
         resources = analyzer.prepare_from_html(html, url=url, sample_cases=sample_cases)
         analyzed = analyzer.run(resources)
 
+        exceptions: List[Exception] = []
+
         for dest_str, template in table.items():
             dest = pathlib.Path(dest_str)
 
             # generate
             try:
                 code = generator.run(analyzed, template_file=template)
-            except NotImplementedError as e:
-                logger.error('generator failed: %s', e)
+            except Exception as e:
+                logger.exception('generator failed: template = %s, dest = %s', template, dest_str)
+                exceptions.append(e)
                 continue
 
             # write
@@ -123,11 +128,27 @@ def prepare_problem(problem: onlinejudge.type.Problem, *, contest: Optional[onli
             subprocess.check_call(['oj', 'download', problem.get_url()], stdout=sys.stdout, stderr=sys.stderr)
         except subprocess.CalledProcessError as e:
             logger.error('samples downloader failed: %s', e)
+            exceptions.append(e)
+
+        if exceptions:
+            raise exceptions[0]
 
 
 def prepare_contest(contest: onlinejudge.type.Contest, *, config: Dict[str, Any], session: requests.Session) -> None:
+    logger.info('prepare the contest: %s', contest.get_url())
+
+    exceptions: List[Exception] = []
+
     for i, problem in enumerate(contest.list_problems()):
-        prepare_problem(problem, contest=contest, config=config, session=session)
+        try:
+            prepare_problem(problem, contest=contest, config=config, session=session)
+
+        except Exception as e:
+            logger.exception('failed to prepare the problem: %s', problem.get_url())
+            exceptions.append(e)
+
+    if exceptions:
+        raise exceptions[0]
 
 
 default_config_path = pathlib.Path(appdirs.user_config_dir('online-judge-tools')) / 'prepare.config.toml'
diff --git a/onlinejudge_template/__about__.py b/onlinejudge_template/__about__.py
index 3ff6d9d..97f7043 100644
--- a/onlinejudge_template/__about__.py
+++ b/onlinejudge_template/__about__.py
@@ -1,3 +1,3 @@
 __title__ = "online-judge-template-generator"
 __url__ = "https://github.com/online-judge-tools/template-generator"
-__version__ = "4.7.2"
+__version__ = "4.8.0"
diff --git a/onlinejudge_template/analyzer/codeforces.py b/onlinejudge_template/analyzer/codeforces.py
new file mode 100644
index 0000000..46da19b
--- /dev/null
+++ b/onlinejudge_template/analyzer/codeforces.py
@@ -0,0 +1,45 @@
+"""
+the module to detect whether the style is multiple cases or not in Codeforces
+"""
+
+import re
+import urllib.parse
+from logging import getLogger
+from typing import *
+
+import bs4
+
+from onlinejudge_template.types import *
+
+logger = getLogger(__name__)
+
+
+class CodeforcesParserError(AnalyzerError):
+    pass
+
+
+def is_codeforces_url(url: str) -> bool:
+    result = urllib.parse.urlparse(url)
+    return result.netloc == 'codeforces.com'
+
+
+def has_multiple_testcases(html: bytes, *, url: str) -> bool:
+    # parse HTML
+    soup = bs4.BeautifulSoup(html, 'html.parser')
+    input_specifications = soup.find_all('div', class_='input-specification')
+    if len(input_specifications) != 1:
+        logger.error("""<div class="input-specification"> is not found or not unique.""")
+        return False
+    input_specification = input_specifications[0]
+
+    logger.debug('parse Input section')
+    p = input_specification.find('p')
+    if p is None:
+        logger.error("""There are no <p> in the Input section.""")
+        return False
+    text = p.text
+
+    # parse the first paragraph
+    logger.debug('parse the first paragraph: %s', text)
+    pattern = r"""[Tt]he +first +line.*integer.*\$t\$.*(number +of.*test|test +cases)|multiple +test +cases"""
+    return bool(re.search(pattern, text))
diff --git a/onlinejudge_template/analyzer/combined.py b/onlinejudge_template/analyzer/combined.py
index 805cc1a..460336a 100644
--- a/onlinejudge_template/analyzer/combined.py
+++ b/onlinejudge_template/analyzer/combined.py
@@ -1,6 +1,7 @@
 from logging import getLogger
 from typing import *
 
+import onlinejudge_template.analyzer.codeforces
 import onlinejudge_template.analyzer.constants
 import onlinejudge_template.analyzer.html
 import onlinejudge_template.analyzer.minimum_tree
@@ -52,6 +53,13 @@ def run(resources: AnalyzerResources) -> AnalyzerResult:
         if resources.html is not None:
             topcoder_class_definition = onlinejudge_template.analyzer.topcoder.parse_topcoder_class_definition(resources.html, url=resources.url)
 
+    multiple_test_cases = False
+    if resources.url is not None and onlinejudge_template.analyzer.codeforces.is_codeforces_url(resources.url):
+        if resources.html is not None:
+            multiple_test_cases = onlinejudge_template.analyzer.codeforces.has_multiple_testcases(resources.html, url=resources.url)
+            if multiple_test_cases:
+                logger.info('Each input of this problem has multiple test cases.')
+
     # parse the format tree for input
     input_format: Optional[FormatNode] = None
     if resources.input_format_string is not None:
@@ -65,9 +73,10 @@ def run(resources: AnalyzerResources) -> AnalyzerResult:
         input_format = onlinejudge_template.analyzer.topcoder.convert_topcoder_class_definition_to_input_format(topcoder_class_definition)
     elif resources.sample_cases:
         input_samples = [case.input.decode() for case in resources.sample_cases]
-        input_format = onlinejudge_template.analyzer.simple_patterns.guess_format_with_pattern_matching(instances=input_samples)
+        if not multiple_test_cases:
+            input_format = onlinejudge_template.analyzer.simple_patterns.guess_format_with_pattern_matching(instances=input_samples)
         if input_format is None:
-            input_format = onlinejudge_template.analyzer.minimum_tree.construct_minimum_input_format_tree(instances=input_samples)
+            input_format = onlinejudge_template.analyzer.minimum_tree.construct_minimum_input_format_tree(instances=input_samples, multiple_test_cases=multiple_test_cases)
 
     # list the variables for input
     input_variables: Optional[Dict[VarName, VarDecl]] = None
@@ -101,9 +110,10 @@ def run(resources: AnalyzerResources) -> AnalyzerResult:
         output_format = onlinejudge_template.analyzer.topcoder.convert_topcoder_class_definition_to_output_format(topcoder_class_definition)
     elif resources.sample_cases:
         if input_format is not None and input_variables is not None:
-            output_format = onlinejudge_template.analyzer.simple_patterns.guess_output_format_with_pattern_matching_using_input_format(instances=resources.sample_cases, input_format=input_format, input_variables=input_variables)
+            if not multiple_test_cases:
+                output_format = onlinejudge_template.analyzer.simple_patterns.guess_output_format_with_pattern_matching_using_input_format(instances=resources.sample_cases, input_format=input_format, input_variables=input_variables)
             if output_format is None:
-                output_format = onlinejudge_template.analyzer.minimum_tree.construct_minimum_output_format_tree_using_input_format(instances=resources.sample_cases, input_format=input_format, input_variables=input_variables)
+                output_format = onlinejudge_template.analyzer.minimum_tree.construct_minimum_output_format_tree_using_input_format(instances=resources.sample_cases, input_format=input_format, input_variables=input_variables, multiple_test_cases=multiple_test_cases)
         else:
             output_samples = [case.output.decode() for case in resources.sample_cases]
             output_format = onlinejudge_template.analyzer.simple_patterns.guess_format_with_pattern_matching(instances=output_samples)
diff --git a/onlinejudge_template/analyzer/match.py b/onlinejudge_template/analyzer/match.py
index a9e09c8..00d6e5b 100644
--- a/onlinejudge_template/analyzer/match.py
+++ b/onlinejudge_template/analyzer/match.py
@@ -31,7 +31,6 @@
 に相当する結果を返します。
 """
 
-import itertools
 from logging import getLogger
 from typing import *
 
@@ -45,11 +44,21 @@ class FormatMatchError(AnalyzerError):
     pass
 
 
-def _get_env(values: Dict[VarName, Dict[Tuple[int, ...], Union[int, float, str]]]) -> Dict[VarName, int]:
-    env: Dict[VarName, int] = {}
+def _get_env(values: Dict[VarName, Dict[Tuple[int, ...], Union[int, float, str]]]) -> Dict[VarName, Union[int, List[int], List[List[int]]]]:
+    env: Dict[VarName, Union[int, List[int], List[List[int]]]] = {}
     for name, value in values.items():
         if () in value and isinstance(value[()], int):
             env[name] = value[()]
+        elif (0, ) in value and isinstance(value[(0, )], int):
+            f: Dict[int, int] = {i: a_i for (i, ), a_i in value.items()}  # type: ignore
+            env[name] = [f[i] for i in range(max(f.keys()) + 1)]
+        elif (0, 0) in value and isinstance(value[(0, 0)], int):
+            g: Dict[int, Dict[int, int]] = {}
+            for (i, j), a_i_j in value.items():
+                if i not in g:
+                    g[i] = {}
+                g[i][j] = a_i_j  # type: ignore
+            env[name] = [[g[i][j] for j in range(max(g[i].keys()) + 1)] for i in range(max(g.keys()) + 1)]
     return env
 
 
@@ -155,17 +164,4 @@ def match_format(
     _match_format_dfs(node, tokens, variables=variables, values=values)
     if tokens:
         raise FormatMatchError(f"""end of tokens is expected, but {repr(tokens[0])} found""")
-
-    # check results
-    env = _get_env(values)
-    for name, decl in variables.items():
-        dims: List[int] = []
-        for str_dim in decl.dims:
-            dim = evaluate(str_dim, env=env)
-            if dim is None:
-                raise FormatMatchError(f"""failed to evaluate: {str_dim}""")
-            dims.append(dim)
-        for ix in itertools.product(*map(lambda n: range(n), dims)):
-            if ix not in values[name]:
-                raise FormatMatchError(f"""matched, but {name}{ix} is not assigned""")
     return values
diff --git a/onlinejudge_template/analyzer/minimum_tree.py b/onlinejudge_template/analyzer/minimum_tree.py
index 85e246f..ce6c8e1 100644
--- a/onlinejudge_template/analyzer/minimum_tree.py
+++ b/onlinejudge_template/analyzer/minimum_tree.py
@@ -89,12 +89,15 @@
 import heapq
 import itertools
 import string
+from logging import getLogger
 from typing import *
 
 import onlinejudge_template.analyzer.node_util as node_util
 from onlinejudge_template.analyzer.match import FormatMatchError, match_format
 from onlinejudge_template.types import *
 
+logger = getLogger(__name__)
+
 
 class _Token(abc.ABC):
     row: int
@@ -385,10 +388,9 @@ def list_next_possible_node(states: List[_MatchState]) -> Iterator[_Node]:
     return
 
 
-def _construct_minimum_input_format_internal_tree(*, instances: List[List[_Token]], initial_env: Optional[List[List[int]]] = None, limit: int = 10000) -> Optional[_Node]:
+def _construct_minimum_input_format_internal_tree(*, instances: List[List[_Token]], initial_env: Optional[List[List[int]]] = None, limit: int = 10000, initial_node: _Node = _PlaceholderNode()) -> Optional[_Node]:
     # init
     que = _PriorityQueue()
-    initial_node = _PlaceholderNode()
     que.push(initial_node.get_tree_size(), initial_node)
     while not que.empty():
         # pop
@@ -434,8 +436,12 @@ class EnvItem(NamedTuple):
     is_counter: bool
 
 
-def _convert_to_format_node(node: _Node, *, env: List[EnvItem], used: Set[VarName]) -> FormatNode:
+def _convert_to_format_node(node: _Node, *, env: List[EnvItem], used: Set[VarName], fixed_names: List[VarName]) -> FormatNode:
     def get_fresh_name() -> VarName:
+        # allow using fixed name for multiple test cases
+        if fixed_names:
+            return fixed_names.pop()  # update the list
+
         for var in map(VarName, string.ascii_letters):
             if var not in used:
                 return var
@@ -462,13 +468,13 @@ def list_indices(index: int) -> List[VarName]:
         used.add(var)
         return SequenceNode(items=[
             ItemNode(name=var, indices=indices),
-            _convert_to_format_node(node.next, env=delta + env, used=used),
+            _convert_to_format_node(node.next, env=delta + env, used=used, fixed_names=fixed_names),
         ])
 
     elif isinstance(node, _NewlineNode):
         return SequenceNode(items=[
             NewlineNode(),
-            _convert_to_format_node(node.next, env=env, used=used),
+            _convert_to_format_node(node.next, env=env, used=used, fixed_names=fixed_names),
         ])
 
     elif isinstance(node, _LoopNode):
@@ -478,11 +484,11 @@ def list_indices(index: int) -> List[VarName]:
         var = get_fresh_name()
 
         used.add(var)
-        body = _convert_to_format_node(node.body, env=[EnvItem(var, True)] + env, used=used)
+        body = _convert_to_format_node(node.body, env=[EnvItem(var, True)] + env, used=used, fixed_names=fixed_names)
         used.remove(var)
         return SequenceNode(items=[
             LoopNode(size=size, name=var, body=body),
-            _convert_to_format_node(node.next, env=env, used=used),
+            _convert_to_format_node(node.next, env=env, used=used, fixed_names=fixed_names),
         ])
 
     elif isinstance(node, _PlaceholderNode):
@@ -491,12 +497,16 @@ def list_indices(index: int) -> List[VarName]:
         assert False
 
 
-def construct_minimum_input_format_tree(*, instances: List[str]) -> Optional[FormatNode]:
+def construct_minimum_input_format_tree(*, instances: List[str], multiple_test_cases: bool = False) -> Optional[FormatNode]:
     tokenized_instances = [list(tokenize_content(instance)) for instance in instances]
-    node = _construct_minimum_input_format_internal_tree(instances=tokenized_instances)
+    if multiple_test_cases:
+        initial_node: _Node = _IntNode(next=_NewlineNode(next=_LoopNode(index=0, delta=0, body=_PlaceholderNode(), next=_EOFNode())))
+    else:
+        initial_node = _PlaceholderNode()
+    node = _construct_minimum_input_format_internal_tree(instances=tokenized_instances, initial_node=initial_node)
     if node is None:
         return None
-    format_node = _convert_to_format_node(node, env=[], used=set())
+    format_node = _convert_to_format_node(node, env=[], used=set(), fixed_names=(multiple_test_cases and [node_util.testcases_varname] or []))
     format_node = node_util.rename_variable_nicely(format_node)
     return node_util.remove_superfluous_sequence_nodes(format_node)
 
@@ -505,7 +515,7 @@ def construct_minimum_output_format_tree(*, instances: List[str]) -> Optional[Fo
     return construct_minimum_input_format_tree(instances=instances)
 
 
-def construct_minimum_output_format_tree_using_input_format(*, instances: List[SampleCase], input_format: FormatNode, input_variables: Dict[VarName, VarDecl]) -> Optional[FormatNode]:
+def construct_minimum_output_format_tree_using_input_format(*, instances: List[SampleCase], input_format: FormatNode, input_variables: Dict[VarName, VarDecl], multiple_test_cases: bool) -> Optional[FormatNode]:
     # prepare environments
     minimizer_env: List[List[int]] = []
     converter_env: List[EnvItem] = []
@@ -513,6 +523,12 @@ def construct_minimum_output_format_tree_using_input_format(*, instances: List[S
     try:
         for i, data in enumerate(instances):
             minimizer_env.append([])
+            print()
+            print(input_format, data.input.decode(), input_variables)
+            print()
+            print(input_format, data.input.decode(), input_variables)
+            print()
+            print(input_format, data.input.decode(), input_variables)
             input_values = match_format(input_format, data.input.decode(), variables=input_variables)
             for name in sorted(input_variables.keys()):
                 decl = input_variables[name]
@@ -524,17 +540,24 @@ def construct_minimum_output_format_tree_using_input_format(*, instances: List[S
                         converter_env.append(EnvItem(name, False))
                 if i == 0:
                     converter_used.add(name)
-    except FormatMatchError:
+    except FormatMatchError as e:
+        logger.debug('failed to match sample input: %s', e)
         output_samples = [case.output.decode() for case in instances]
         return construct_minimum_output_format_tree(instances=output_samples)
 
     # construct the tree
     tokenized_instances = [list(tokenize_content(instance.output.decode())) for instance in instances]
-    node = _construct_minimum_input_format_internal_tree(instances=tokenized_instances, initial_env=minimizer_env)
+    initial_node: _Node = _PlaceholderNode()
+    if multiple_test_cases:
+        for i, item in enumerate(converter_env):
+            if item.name == node_util.testcases_varname:
+                initial_node = _LoopNode(index=i, delta=0, body=_PlaceholderNode(), next=_EOFNode())
+                break
+    node = _construct_minimum_input_format_internal_tree(instances=tokenized_instances, initial_env=minimizer_env, initial_node=initial_node)
     if node is None:
         return None
 
     # make format node
-    format_node = _convert_to_format_node(node, env=converter_env, used=converter_used)
+    format_node = _convert_to_format_node(node, env=converter_env, used=converter_used, fixed_names=[])
     format_node = node_util.rename_variable_nicely(format_node, used=converter_used)
     return node_util.remove_superfluous_sequence_nodes(format_node)
diff --git a/onlinejudge_template/analyzer/node_util.py b/onlinejudge_template/analyzer/node_util.py
index 3115d2a..87af1f8 100644
--- a/onlinejudge_template/analyzer/node_util.py
+++ b/onlinejudge_template/analyzer/node_util.py
@@ -53,9 +53,16 @@ def _get_nice_counter_name(*, used: Set[VarName]) -> VarName:
     assert False
 
 
+# use the name `testcases` for variables which describes the number of test cases.
+testcases_varname: VarName = VarName('testcases')
+
+
 def _rename_variable_nicely_dfs(node: FormatNode, *, replace: Dict[VarName, VarName], used: Set[VarName]) -> FormatNode:
     if isinstance(node, ItemNode):
-        name = _get_nice_variable_name(used=used)
+        if node.name == testcases_varname:
+            name = testcases_varname
+        else:
+            name = _get_nice_variable_name(used=used)
         indices = [simplify.rename_variables_in_expr(index, replace=replace) for index in node.indices]
 
         assert node.name not in replace
diff --git a/onlinejudge_template/analyzer/output_types.py b/onlinejudge_template/analyzer/output_types.py
index ce2d717..5779757 100644
--- a/onlinejudge_template/analyzer/output_types.py
+++ b/onlinejudge_template/analyzer/output_types.py
@@ -27,6 +27,15 @@ def _get_variable_on_code(*, decl: VarDecl, indices: List[Expr], decls: Dict[Var
     return var
 
 
+def match_indices(*, indices: List[Expr], names: List[str]) -> bool:
+    if len(indices) != len(names):
+        return False
+    for index, name in zip(indices, names):
+        if index not in (name + ' - 1', name, name + ' + 1'):
+            return False
+    return True
+
+
 def analyze_output_type(*, output_format: FormatNode, output_variables: Dict[VarName, VarDecl], constants: Dict[VarName, ConstantDecl]) -> Optional[OutputType]:
     node = output_format
     decls = output_variables
@@ -43,7 +52,7 @@ def analyze_output_type(*, output_format: FormatNode, output_variables: Dict[Var
                     return YesNoOutputType(name=Expr('ans'), yes='YES', no='NO')
                 if 'FIRST' in constants and 'SECOND' in constants and type == VarType.String:
                     return YesNoOutputType(name=Expr('ans'), yes='FIRST', no='SECOND')
-                return OneOutputType(name=Expr('ans'), type=type)
+            return OneOutputType(name=Expr('ans'), type=type)
 
     # pattern:
     #     x y
@@ -56,8 +65,7 @@ def analyze_output_type(*, output_format: FormatNode, output_variables: Dict[Var
             name2 = item1.name
             type1 = decls[name1].type
             type2 = decls[name2].type
-            if type1 is not None and type2 is not None:
-                return TwoOutputType(name1=Expr(name1), type1=type1, name2=Expr(name2), type2=type2, print_newline_after_item=False)
+            return TwoOutputType(name1=Expr(name1), type1=type1, name2=Expr(name2), type2=type2, print_newline_after_item=False)
 
     # pattern:
     #     x
@@ -72,8 +80,19 @@ def analyze_output_type(*, output_format: FormatNode, output_variables: Dict[Var
             name2 = item2.name
             type1 = decls[name1].type
             type2 = decls[name2].type
-            if type1 is not None and type2 is not None:
-                return TwoOutputType(name1=Expr(name1), type1=type1, name2=Expr(name2), type2=type2, print_newline_after_item=False)
+            return TwoOutputType(name1=Expr(name1), type1=type1, name2=Expr(name2), type2=type2, print_newline_after_item=False)
+
+    # pattern:
+    #     a_1 ... a_n
+    if isinstance(node, SequenceNode) and len(node.items) == 2:
+        item0 = node.items[0]
+        item1 = node.items[1]
+        if isinstance(item1, NewlineNode):
+            if isinstance(item0, LoopNode) and isinstance(item0.body, ItemNode) and match_indices(indices=item0.body.indices, names=[item0.name]):
+                type = decls[item0.body.name].type
+                subscripted_name = _get_variable_on_code(decl=decls[item0.body.name], indices=item0.body.indices, decls=decls)
+                counter_name = item0.name
+                return VectorOutputType(name=VarName('ans'), type=type, subscripted_name=subscripted_name, counter_name=counter_name, print_size=False, print_newline_after_size=False, print_newline_after_item=False)
 
     # pattern:
     #     n
@@ -84,12 +103,11 @@ def analyze_output_type(*, output_format: FormatNode, output_variables: Dict[Var
         item2 = node.items[2]
         item3 = node.items[3]
         if isinstance(item0, ItemNode) and isinstance(item1, NewlineNode) and isinstance(item3, NewlineNode):
-            if isinstance(item2, LoopNode) and isinstance(item2.body, ItemNode) and item2.size == item0.name and item2.body.indices == [item2.name]:
+            if isinstance(item2, LoopNode) and isinstance(item2.body, ItemNode) and item2.size == item0.name and match_indices(indices=item2.body.indices, names=[item2.name]):
                 type = decls[item2.body.name].type
                 subscripted_name = _get_variable_on_code(decl=decls[item2.body.name], indices=item2.body.indices, decls=decls)
                 counter_name = item2.name
-                if type is not None:
-                    return VectorOutputType(name=VarName('ans'), type=type, subscripted_name=subscripted_name, counter_name=counter_name, print_size=True, print_newline_after_size=True, print_newline_after_item=False)
+                return VectorOutputType(name=VarName('ans'), type=type, subscripted_name=subscripted_name, counter_name=counter_name, print_size=True, print_newline_after_size=True, print_newline_after_item=False)
 
     # pattern:
     #     n a_1 ... a_n
@@ -98,12 +116,26 @@ def analyze_output_type(*, output_format: FormatNode, output_variables: Dict[Var
         item1 = node.items[1]
         item2 = node.items[2]
         if isinstance(item0, ItemNode) and isinstance(item2, NewlineNode):
-            if isinstance(item1, LoopNode) and isinstance(item1.body, ItemNode) and item1.size == item0.name and item1.body.indices == [item1.name]:
+            if isinstance(item1, LoopNode) and isinstance(item1.body, ItemNode) and item1.size == item0.name and match_indices(indices=item1.body.indices, names=[item1.name]):
                 type = decls[item1.body.name].type
                 subscripted_name = _get_variable_on_code(decl=decls[item1.body.name], indices=item1.body.indices, decls=decls)
                 counter_name = item1.name
-                if type is not None:
-                    return VectorOutputType(name=VarName('ans'), type=type, subscripted_name=subscripted_name, counter_name=counter_name, print_size=True, print_newline_after_size=False, print_newline_after_item=False)
+                return VectorOutputType(name=VarName('ans'), type=type, subscripted_name=subscripted_name, counter_name=counter_name, print_size=True, print_newline_after_size=False, print_newline_after_item=False)
+
+    # pattern:
+    #     a_1
+    #     ...
+    #     a_n
+    if isinstance(node, SequenceNode) and len(node.items) == 3:
+        item0 = node.items[0]
+        if isinstance(item0, LoopNode) and isinstance(item0.body, SequenceNode) and len(item0.body.items) == 2:
+            item1 = node.items[0]
+            item2 = node.items[1]
+            if isinstance(item1, ItemNode) and isinstance(item2, NewlineNode) and match_indices(indices=item1.indices, names=[item0.name]):
+                type = decls[item1.name].type
+                subscripted_name = _get_variable_on_code(decl=decls[item1.name], indices=item1.indices, decls=decls)
+                counter_name = item0.name
+                return VectorOutputType(name=VarName('ans'), type=type, subscripted_name=subscripted_name, counter_name=counter_name, print_size=False, print_newline_after_size=False, print_newline_after_item=True)
 
     # pattern:
     #     n
@@ -118,11 +150,10 @@ def analyze_output_type(*, output_format: FormatNode, output_variables: Dict[Var
             if isinstance(item2, LoopNode) and isinstance(item2.body, SequenceNode) and len(item2.body.items) == 2:
                 item3 = node.items[0]
                 item4 = node.items[1]
-                if isinstance(item3, ItemNode) and isinstance(item4, NewlineNode) and item2.size == item0.name and item3.indices == [item0.name]:
+                if isinstance(item3, ItemNode) and isinstance(item4, NewlineNode) and item2.size == item0.name and match_indices(indices=item3.indices, names=[item2.name]):
                     type = decls[item3.name].type
                     subscripted_name = _get_variable_on_code(decl=decls[item3.name], indices=item3.indices, decls=decls)
                     counter_name = item2.name
-                    if type is not None:
-                        return VectorOutputType(name=VarName('ans'), type=type, subscripted_name=subscripted_name, counter_name=counter_name, print_size=True, print_newline_after_size=True, print_newline_after_item=True)
+                    return VectorOutputType(name=VarName('ans'), type=type, subscripted_name=subscripted_name, counter_name=counter_name, print_size=True, print_newline_after_size=True, print_newline_after_item=True)
 
     return None
diff --git a/onlinejudge_template/generator/_cplusplus.py b/onlinejudge_template/generator/_cplusplus.py
index afe38bf..4d677e5 100644
--- a/onlinejudge_template/generator/_cplusplus.py
+++ b/onlinejudge_template/generator/_cplusplus.py
@@ -33,13 +33,10 @@ def __init__(self, expr: Tuple[str, Optional[VarType]]):
 
 
 class OutputTokensNode(CPlusPlusNode):
-    def __init__(self, exprs: List[Tuple[str, Optional[VarType]]]):
-        self.exprs = exprs
-
-
-class OutputNewlineNode(CPlusPlusNode):
-    def __init__(self, exprs: List[Tuple[str, Optional[VarType]]]):
+    def __init__(self, exprs: List[Tuple[str, Optional[VarType]]], end: str):
+        assert end in ('', ' ', '\n')
         self.exprs = exprs
+        self.end = end
 
 
 class SentencesNode(CPlusPlusNode):
diff --git a/onlinejudge_template/generator/cplusplus.py b/onlinejudge_template/generator/cplusplus.py
index 339aaa0..5fdf7c3 100644
--- a/onlinejudge_template/generator/cplusplus.py
+++ b/onlinejudge_template/generator/cplusplus.py
@@ -37,6 +37,7 @@
 - :func:`write_input`
 """
 
+from logging import getLogger
 from typing import *
 
 import onlinejudge_template.generator._utils as utils
@@ -44,6 +45,8 @@
 from onlinejudge_template.generator._cplusplus import *
 from onlinejudge_template.types import *
 
+logger = getLogger(__name__)
+
 
 def _join_with_indent(lines: Iterator[str], *, nest: int, data: Dict[str, Any]) -> str:
     indent = utils.get_indent(data=data)
@@ -90,7 +93,7 @@ def _read_variables(exprs: List[Tuple[str, Optional[VarType]]], *, data: Dict[st
         return [f"""scanf("{specifiers}"{', '.join(arguments)});"""]
     elif scanner is None or scanner in ('cin', 'std::cin'):
         items = []
-        items.append(f"""{_get_std(data=data)}cin""")
+        items.append(f"""std::cin""")
         for expr, _ in exprs:
             items.append(expr)
         return [" >> ".join(items) + ";"]
@@ -100,11 +103,12 @@ def _read_variables(exprs: List[Tuple[str, Optional[VarType]]], *, data: Dict[st
         raise CPlusPlusGeneratorError(f"""invalid "scanner" config: {scanner}""")
 
 
-def _write_variables(exprs: List[Tuple[str, Optional[VarType]]], *, newline: bool, data: Dict[str, Any]) -> List[str]:
+def _write_variables(exprs: List[Tuple[str, Optional[VarType]]], *, end: str, data: Dict[str, Any]) -> List[str]:
     """
     :raises CPlusPlusGeneratorError:
     """
 
+    assert end in ('', ' ', '\n')
     printer = data['config'].get('printer')
     if printer == 'printf':
         specifiers = ''
@@ -112,18 +116,23 @@ def _write_variables(exprs: List[Tuple[str, Optional[VarType]]], *, newline: boo
         for expr, type in exprs:
             specifiers += _get_base_type_format_specifier(type, name=expr, data=data)
             arguments.append(expr)
-        return [f"""printf("{specifiers}\\n"{', '.join(arguments)});"""]
+        if end == '\n':
+            end = '\\n'
+        return [f"""printf("{specifiers}{end}"{', '.join(arguments)});"""]
     elif printer is None or printer in ('cout', 'std::cout'):
         items = []
-        items.append(f"""{_get_std(data=data)}cout""")
+        items.append(f"""std::cout""")
         for i, (expr, _) in enumerate(exprs):
             if i:
                 items.append("""' '""")
             items.append(expr)
-        items.append(f"""{_get_std(data=data)}endl""")
+        if end == ' ':
+            items.append("' '")
+        elif end == '\n':
+            items.append("'\\n'")
         return [" << ".join(items) + ";"]
     elif callable(printer):
-        return printer(exprs, newline=newline)
+        return printer(exprs, newline=(end == '\n'))
     else:
         raise CPlusPlusGeneratorError(f"""invalid "printer" config: {printer}""")
 
@@ -143,14 +152,7 @@ def _generate_variable(expr: Tuple[str, Optional[VarType]], *, data: Dict[str, A
     else:
         raise CPlusPlusGeneratorError(f"""cannot generate a variable of type {type}: {repr(name)}""")
 
-    yield f"""{name} = {_get_std(data=data)}uniform_int_distribution<{_get_base_type(type, data=data)}>({l}, {r - 1})(gen);"""
-
-
-def _get_std(data: Dict['str', Any]) -> str:
-    if data['config'].get('using_namespace_std'):
-        return ''
-    else:
-        return 'std::'
+    yield f"""{name} = std::uniform_int_distribution<{_get_base_type(type, data=data)}>({l}, {r - 1})(gen);"""
 
 
 def _get_base_type(type: Optional[VarType], *, data: Dict[str, Any]) -> str:
@@ -161,7 +163,7 @@ def _get_base_type(type: Optional[VarType], *, data: Dict[str, Any]) -> str:
     elif type == VarType.Float:
         return "double"
     elif type == VarType.String:
-        return f"""{_get_std(data=data)}string"""
+        return f"""std::string"""
     elif type == VarType.Char:
         return "char"
     elif type is None:
@@ -198,7 +200,7 @@ def _get_type_and_ctor(decl: VarDecl, *, data: Dict[str, Any]) -> Tuple[str, str
         sndarg = f""", {type}({ctor})""" if ctor else ''
         ctor = f"""({dim}{sndarg})"""
         space = ' ' if type.endswith('>') else ''
-        type = f"""{_get_std(data=data)}vector<{type}{space}>"""
+        type = f"""std::vector<{type}{space}>"""
     return type, ctor
 
 
@@ -216,7 +218,7 @@ def _declare_variables(decls: List[VarDecl], *, data: Dict[str, Any]) -> Iterato
     for decl in decls:
         type, ctor = _get_type_and_ctor(decl, data=data)
         if last_type != type and last_type is not None:
-            yield f"""{type} {", ".join(last_inits)};"""
+            yield f"""{last_type} {", ".join(last_inits)};"""
             last_inits = []
         last_type = type
         last_inits.append(f"""{decl.name}{ctor}""")
@@ -279,6 +281,20 @@ def _read_input_dfs(node: FormatNode, *, declared: Set[str], initialized: Set[st
         assert False
 
 
+def _has_trailing_space(node: CPlusPlusNode) -> bool:
+    if isinstance(node, OutputTokensNode):
+        return node.end != ''
+    elif isinstance(node, SentencesNode):
+        if not node:
+            return False
+        else:
+            return _has_trailing_space(node.sentences[-1])
+    elif isinstance(node, RepeatNode):
+        return _has_trailing_space(node.body)
+    else:
+        assert False
+
+
 def _write_output_dfs(node: FormatNode, *, decls: Dict[VarName, VarDecl], data: Dict[str, Any]) -> CPlusPlusNode:
     """
     :raises CPlusPlusGeneratorError:
@@ -287,16 +303,21 @@ def _write_output_dfs(node: FormatNode, *, decls: Dict[VarName, VarDecl], data:
     if isinstance(node, ItemNode):
         decl = decls[node.name]
         var = _get_variable(decl=decl, indices=node.indices, decls=decls)
-        return OutputTokensNode(exprs=[(VarName(var), decl.type)])
+        return OutputTokensNode(exprs=[(VarName(var), decl.type)], end='')
     elif isinstance(node, NewlineNode):
-        return OutputNewlineNode(exprs=[])
+        return OutputTokensNode(exprs=[], end='\n')
     elif isinstance(node, SequenceNode):
         sentences = []
-        for item in node.items:
-            sentences.append(_write_output_dfs(item, decls=decls, data=data))
+        for i, item in enumerate(node.items):
+            sentence = _write_output_dfs(item, decls=decls, data=data)
+            sentences.append(sentence)
+            if i + 1 < len(node.items) and not _has_trailing_space(sentence):
+                sentences.append(OutputTokensNode(exprs=[], end=' '))
         return SentencesNode(sentences=sentences)
     elif isinstance(node, LoopNode):
         body = _write_output_dfs(node.body, decls=decls, data=data)
+        if not _has_trailing_space(body):
+            body = SentencesNode(sentences=[body, OutputTokensNode(exprs=[], end=' ')])
         result = RepeatNode(name=node.name, size=node.size, body=body)
         return result
     else:
@@ -310,8 +331,6 @@ def _optimize_syntax_tree(node: CPlusPlusNode, *, data: Dict[str, Any]) -> CPlus
         return node
     elif isinstance(node, OutputTokensNode):
         return node
-    elif isinstance(node, OutputNewlineNode):
-        return node
     elif isinstance(node, GenerateNode):
         return node
     elif isinstance(node, SentencesNode):
@@ -323,10 +342,9 @@ def _optimize_syntax_tree(node: CPlusPlusNode, *, data: Dict[str, Any]) -> CPlus
                 sentences[-1].decls.extend(sentence.decls)
             elif sentences and isinstance(sentences[-1], InputNode) and isinstance(sentence, InputNode):
                 sentences[-1].exprs.extend(sentence.exprs)
-            elif sentences and isinstance(sentences[-1], OutputTokensNode) and isinstance(sentence, OutputTokensNode):
+            elif sentences and isinstance(sentences[-1], OutputTokensNode) and sentences[-1].end != '\n' and isinstance(sentence, OutputTokensNode):
                 sentences[-1].exprs.extend(sentence.exprs)
-            elif sentences and isinstance(sentences[-1], OutputTokensNode) and isinstance(sentence, OutputNewlineNode):
-                sentences[-1] = OutputNewlineNode(exprs=sentences[-1].exprs + sentence.exprs)
+                sentences[-1].end = sentence.end
             elif isinstance(sentence, SentencesNode):
                 que = sentence.sentences + que
             else:
@@ -346,9 +364,7 @@ def _serialize_syntax_tree(node: CPlusPlusNode, *, data: Dict[str, Any]) -> Iter
     elif isinstance(node, InputNode):
         yield from _read_variables(node.exprs, data=data)
     elif isinstance(node, OutputTokensNode):
-        yield from _write_variables(node.exprs, newline=False, data=data)
-    elif isinstance(node, OutputNewlineNode):
-        yield from _write_variables(node.exprs, newline=True, data=data)
+        yield from _write_variables(node.exprs, end=node.end, data=data)
     elif isinstance(node, GenerateNode):
         yield from _generate_variable(node.expr, data=data)
     elif isinstance(node, SentencesNode):
@@ -368,26 +384,11 @@ def _read_input_fallback(message: str, *, data: Dict[str, Any], nest: int) -> st
     lines = []
     lines.append(f"""// {message}""")
     lines.append(f"""// TODO: edit here""")
-    try:
-        lines.extend(_declare_variables([VarDecl(name=VarName('n'), type=VarType.IndexInt, dims=[], bases=[], depending=set())], data=data))
-    except CPlusPlusGeneratorError:
-        lines.append(f"""int n;""")
-    try:
-        lines.extend(_read_variables([('n', VarType.IndexInt)], data=data))
-    except CPlusPlusGeneratorError:
-        lines.append(f"""{_get_std(data=data)}scanf("%d", &n);""")
-    try:
-        lines.extend(_declare_variables([VarDecl(name=VarName('a'), type=VarType.ValueInt, dims=[Expr('n')], bases=[Expr('0')], depending=set([VarName('n')]))], data=data))
-    except CPlusPlusGeneratorError:
-        lines.append(f"""{_get_std(data=data)}vector<{_get_base_type(VarType.ValueInt, data=data)}> a(n);""")
-    try:
-        lines.append(_declare_loop(var=VarName('i'), size=Expr('n'), data=data) + " {")
-    except CPlusPlusGeneratorError:
-        lines.append("""for (int i = 0; i < n; ++i) {""")
-    try:
-        lines.extend(_read_variables([('a[i]', VarType.ValueInt)], data=data))
-    except CPlusPlusGeneratorError:
-        lines.append(f"""{_get_std(data=data)}scanf("{_get_base_type_format_specifier(VarType.ValueInt, name="a", data=data)}", &a[i]);""")
+    lines.extend(_declare_variables([VarDecl(name=VarName('n'), type=VarType.IndexInt, dims=[], bases=[], depending=set())], data=data))
+    lines.extend(_read_variables([('n', VarType.IndexInt)], data=data))
+    lines.extend(_declare_variables([VarDecl(name=VarName('a'), type=VarType.ValueInt, dims=[Expr('n')], bases=[Expr('0')], depending=set([VarName('n')]))], data=data))
+    lines.append(_declare_loop(var=VarName('i'), size=Expr('n'), data=data) + " {")
+    lines.extend(_read_variables([('a[i]', VarType.ValueInt)], data=data))
     lines.append("""}""")
     return _join_with_indent(iter(lines), nest=nest, data=data)
 
@@ -397,41 +398,23 @@ def read_input(data: Dict[str, Any], *, nest: int = 1) -> str:
     if analyzed.input_format is None or analyzed.input_variables is None:
         return _read_input_fallback(message="failed to analyze input format", data=data, nest=nest)
 
-    try:
-        node = _read_input_dfs(analyzed.input_format, declared=set(), initialized=set(), decls=analyzed.input_variables, data=data)
-    except CPlusPlusGeneratorError as e:
-        return _read_input_fallback(message="failed to generate input part: " + str(e), data=data, nest=nest)
+    node = _read_input_dfs(analyzed.input_format, declared=set(), initialized=set(), decls=analyzed.input_variables, data=data)
     node = _optimize_syntax_tree(node, data=data)
     lines = list(_serialize_syntax_tree(node, data=data))
     return _join_with_indent(iter(lines), nest=nest, data=data)
 
 
-def _generate_input_fallback(message: str, *, data: Dict[str, Any], nest: int) -> str:
+def _generate_input_fallback(message: str, data: Dict[str, Any], *, nest: int = 1) -> str:
     lines = []
     lines.append(f"""// {message}""")
     lines.append(f"""// TODO: edit here""")
-    lines.append(f"""{_get_std(data=data)}random_device device;""")
-    lines.append(f"""{_get_std(data=data)}default_random_engine gen(device());""")
-    try:
-        lines.extend(_declare_variables([VarDecl(name=VarName('n'), type=VarType.IndexInt, dims=[], bases=[], depending=set())], data=data))
-    except CPlusPlusGeneratorError:
-        lines.append(f"""int n;""")
-    try:
-        lines.extend(_generate_variable(('n', VarType.IndexInt), data=data))
-    except CPlusPlusGeneratorError:
-        lines.append(f"""n = {_get_std(data=data)}uniform_int_distribution<int>(0, 100000)(gen);""")
-    try:
-        lines.extend(_declare_variables([VarDecl(name=VarName('a'), type=VarType.ValueInt, dims=[Expr('n')], bases=[Expr('0')], depending=set([VarName('n')]))], data=data))
-    except CPlusPlusGeneratorError:
-        lines.append(f"""{_get_std(data=data)}vector<{_get_base_type(VarType.ValueInt, data=data)}> a(n);""")
-    try:
-        lines.append(_declare_loop(var=VarName('i'), size='n', data=data) + " {")
-    except CPlusPlusGeneratorError:
-        lines.append("""for (int i = 0; i < n; ++i) {""")
-    try:
-        lines.extend(_generate_variable(('a[i]', VarType.ValueInt), data=data))
-    except CPlusPlusGeneratorError:
-        lines.append(f"""a[i] = {_get_std(data=data)}uniform_int_distribution<{_get_base_type(VarType.ValueInt, data=data)}>(0, 1000000000)(gen);""")
+    lines.append(f"""std::random_device device;""")
+    lines.append(f"""std::default_random_engine gen(device());""")
+    lines.extend(_declare_variables([VarDecl(name=VarName('n'), type=VarType.IndexInt, dims=[], bases=[], depending=set())], data=data))
+    lines.extend(_generate_variable(('n', VarType.IndexInt), data=data))
+    lines.extend(_declare_variables([VarDecl(name=VarName('a'), type=VarType.ValueInt, dims=[Expr('n')], bases=[Expr('0')], depending=set([VarName('n')]))], data=data))
+    lines.append(_declare_loop(var=VarName('i'), size='n', data=data) + " {")
+    lines.extend(_generate_variable(('a[i]', VarType.ValueInt), data=data))
     lines.append("""}""")
     return _join_with_indent(iter(lines), nest=nest, data=data)
 
@@ -441,45 +424,33 @@ def generate_input(data: Dict[str, Any], *, nest: int = 1) -> str:
     if analyzed.input_format is None or analyzed.input_variables is None:
         return _generate_input_fallback(message="failed to analyze input format", data=data, nest=nest)
 
-    try:
-        make_node = lambda var, type: GenerateNode(expr=(var, type))
-        node = _read_input_dfs(analyzed.input_format, declared=set(), initialized=set(), decls=analyzed.input_variables, data=data, make_node=make_node)
-    except CPlusPlusGeneratorError as e:
-        return _read_input_fallback(message="failed to generate input part: " + str(e), data=data, nest=nest)
+    make_node = lambda var, type: GenerateNode(expr=(var, type))
+    node = _read_input_dfs(analyzed.input_format, declared=set(), initialized=set(), decls=analyzed.input_variables, data=data, make_node=make_node)
     node = _optimize_syntax_tree(node, data=data)
     lines = list(_serialize_syntax_tree(node, data=data))
     return _join_with_indent(iter(lines), nest=nest, data=data)
 
 
-def _write_input_fallback(message: str, *, data: Dict[str, Any], nest: int) -> str:
+def _write_input_fallback(message: str, data: Dict[str, Any], *, nest: int = 1) -> str:
     lines = []
     lines.append(f"""// {message}""")
     lines.append(f"""// TODO: edit here""")
-    try:
-        lines.extend(_write_variables([('n', VarType.IndexInt)], newline=True, data=data))
-    except CPlusPlusGeneratorError:
-        lines.append(f"""{_get_std(data=data)}printf("%d\n", ans);""")
-    try:
-        lines.append(_declare_loop(var=VarName('i'), size='n', data=data) + " {")
-    except CPlusPlusGeneratorError:
-        lines.append("""for (int i = 0; i < n; ++i) {""")
-    try:
-        lines.extend(_read_variables([('a[i]', VarType.ValueInt)], data=data))
-    except CPlusPlusGeneratorError:
-        lines.append(f"""{_get_std(data=data)}printf("{_get_base_type(VarType.ValueInt, data=data)}%c", &a[i], i < n - 1 ? ' ' : '\\n');""")
+    lines.extend(_write_variables([('n', VarType.IndexInt)], end='\n', data=data))
+    lines.append(_declare_loop(var=VarName('i'), size='n', data=data) + " {")
+    lines.extend(_read_variables([('a[i]', VarType.ValueInt)], data=data))
     lines.append("""}""")
     return _join_with_indent(iter(lines), nest=nest, data=data)
 
 
 def write_input(data: Dict[str, Any], *, nest: int = 1) -> str:
+    if data['config'].get('using_namespace_std') == False:
+        logger.warning('Now `data["config"]["using_namespace_std"] = False` is deprecated and has no meaning.')
+
     analyzed = utils.get_analyzed(data)
     if analyzed.input_format is None or analyzed.input_variables is None:
         return _write_input_fallback(message="failed to analyze input format", data=data, nest=nest)
 
-    try:
-        node = _write_output_dfs(analyzed.input_format, decls=analyzed.input_variables, data=data)
-    except CPlusPlusGeneratorError as e:
-        return _write_input_fallback(message="failed to generate input part: " + str(e), data=data, nest=nest)
+    node = _write_output_dfs(analyzed.input_format, decls=analyzed.input_variables, data=data)
     node = _optimize_syntax_tree(node, data=data)
     lines = list(_serialize_syntax_tree(node, data=data))
     return _join_with_indent(iter(lines), nest=nest, data=data)
@@ -489,10 +460,7 @@ def _write_output_fallback(message: str, *, data: Dict[str, Any], nest: int) ->
     lines = []
     lines.append(f"""// {message}""")
     lines.append(f"""// TODO: edit here""")
-    try:
-        lines.extend(_write_variables([('ans', VarType.ValueInt)], newline=True, data=data))
-    except CPlusPlusGeneratorError:
-        lines.append(f"""{_get_std(data=data)}printf("%d\n", ans);""")
+    lines.extend(_write_variables([('ans', VarType.ValueInt)], end='\n', data=data))
     return _join_with_indent(iter(lines), nest=nest, data=data)
 
 
@@ -501,44 +469,45 @@ def write_output(data: Dict[str, Any], *, nest: int = 1) -> str:
     output_type = analyzed.output_type
 
     if isinstance(output_type, OneOutputType):
-        node: CPlusPlusNode = OutputNewlineNode(exprs=[(output_type.name, output_type.type)])
+        node: CPlusPlusNode = OutputTokensNode(exprs=[(output_type.name, output_type.type)], end='\n')
 
     elif isinstance(output_type, TwoOutputType):
         sentences: List[CPlusPlusNode] = []
-        sentences.append(OutputTokensNode(exprs=[(output_type.name1, output_type.type1)]))
+        sentences.append(OutputTokensNode(exprs=[(output_type.name1, output_type.type1)], end=''))
         if output_type.print_newline_after_item:
-            sentences.append(OutputNewlineNode(exprs=[]))
-        sentences.append(OutputNewlineNode(exprs=[(output_type.name2, output_type.type2)]))
+            sentences.append(OutputTokensNode(exprs=[], end='\n'))
+        sentences.append(OutputTokensNode(exprs=[(output_type.name2, output_type.type2)], end='\n'))
         node = SentencesNode(sentences=sentences)
 
     elif isinstance(output_type, YesNoOutputType):
         expr = f"""({output_type.name} ? {output_type.yes} : {output_type.no})"""
-        node = OutputNewlineNode(exprs=[(expr, VarType.String)])
+        node = OutputTokensNode(exprs=[(expr, VarType.String)], end='\n')
 
     elif isinstance(output_type, VectorOutputType):
         inner_sentences: List[CPlusPlusNode] = []
-        inner_sentences.append(OutputTokensNode(exprs=[(output_type.subscripted_name, output_type.type)]))
+        inner_sentences.append(OutputTokensNode(exprs=[(output_type.subscripted_name, output_type.type)], end=''))
         if output_type.print_newline_after_item:
-            inner_sentences.append(OutputNewlineNode(exprs=[]))
+            end = '\n'
+        else:
+            end = ' '
+        inner_sentences.append(OutputTokensNode(exprs=[], end=end))
 
         sentences = []
         size = f"""({_get_base_type(VarType.IndexInt, data=data)}){output_type.name}.size()"""
         if output_type.print_size:
-            sentences.append(OutputTokensNode(exprs=[(size, VarType.IndexInt)]))
+            sentences.append(OutputTokensNode(exprs=[(size, VarType.IndexInt)], end=''))
             if output_type.print_newline_after_size:
-                sentences.append(OutputNewlineNode(exprs=[]))
+                sentences.append(OutputTokensNode(exprs=[], end='\n'))
         sentences.append(RepeatNode(name=output_type.counter_name, size=size, body=SentencesNode(sentences=inner_sentences)))
         if not output_type.print_newline_after_item:
-            inner_sentences.append(OutputNewlineNode(exprs=[]))
+            sentences.append(OutputTokensNode(exprs=[], end='\n'))
         node = SentencesNode(sentences=sentences)
 
     elif output_type is None:
         if analyzed.output_format is None or analyzed.output_variables is None:
             return _write_output_fallback(message="failed to analyze output format", data=data, nest=nest)
-        try:
+        else:
             node = _write_output_dfs(analyzed.output_format, decls=analyzed.output_variables, data=data)
-        except CPlusPlusGeneratorError as e:
-            return _write_output_fallback(message="failed to generate output part: " + str(e), data=data, nest=nest)
 
     else:
         assert False
@@ -551,7 +520,7 @@ def write_output(data: Dict[str, Any], *, nest: int = 1) -> str:
 def formal_arguments(data: Dict[str, Any]) -> str:
     analyzed = utils.get_analyzed(data)
     if analyzed.input_format is None or analyzed.input_variables is None:
-        return f"""int n, const {_get_std(data=data)}vector<int64_t> & a"""
+        return f"""int n, const std::vector<int64_t> &a"""
 
     decls = analyzed.input_variables
     decls = utils._filter_ignored_variables(decls, data=data)
@@ -561,10 +530,10 @@ def formal_arguments(data: Dict[str, Any]) -> str:
         type = _get_base_type(decl.type, data=data)
         for _ in reversed(decl.dims):
             space = ' ' if type.endswith('>') else ''
-            type = f"""{_get_std(data=data)}vector<{type}{space}>"""
+            type = f"""std::vector<{type}{space}>"""
         if decl.dims:
             type = f"""const {type} &"""
-        args.append(f"""{type} {name}""")
+        args.append(f"""{type} {name}""".replace('& ', '&'))
     return ', '.join(args)
 
 
@@ -584,11 +553,11 @@ def return_type(data: Dict[str, Any]) -> str:
     if isinstance(output_type, OneOutputType):
         return _get_base_type(output_type.type, data=data)
     elif isinstance(output_type, TwoOutputType):
-        return f"""{_get_std(data=data)}pair<{_get_base_type(output_type.type1, data=data)}, {_get_base_type(output_type.type2, data=data)}>"""
+        return f"""std::pair<{_get_base_type(output_type.type1, data=data)}, {_get_base_type(output_type.type2, data=data)}>"""
     elif isinstance(output_type, YesNoOutputType):
         return "bool"
     elif isinstance(output_type, VectorOutputType):
-        return f"""{_get_std(data=data)}vector<{_get_base_type(output_type.type, data=data)}>"""
+        return f"""std::vector<{_get_base_type(output_type.type, data=data)}>"""
     elif output_type is None:
         return "auto"
     else:
diff --git a/onlinejudge_template/types.py b/onlinejudge_template/types.py
index fb078d9..8c311ff 100644
--- a/onlinejudge_template/types.py
+++ b/onlinejudge_template/types.py
@@ -100,21 +100,21 @@ def __init__(self, *, name: Expr, yes: str, no: str):
 
 class OneOutputType(OutputType):
     name: Expr
-    type: VarType
+    type: Optional[VarType]
 
-    def __init__(self, *, name: Expr, type: VarType):
+    def __init__(self, *, name: Expr, type: Optional[VarType]):
         self.name = name
         self.type = type
 
 
 class TwoOutputType(OutputType):
     name1: Expr
-    type1: VarType
+    type1: Optional[VarType]
     name2: Expr
-    type2: VarType
+    type2: Optional[VarType]
     print_newline_after_item: bool
 
-    def __init__(self, *, name1: Expr, type1: VarType, name2: Expr, type2: VarType, print_newline_after_item: bool):
+    def __init__(self, *, name1: Expr, type1: Optional[VarType], name2: Expr, type2: Optional[VarType], print_newline_after_item: bool):
         self.name1 = name1
         self.type1 = type1
         self.name2 = name2
@@ -124,14 +124,14 @@ def __init__(self, *, name1: Expr, type1: VarType, name2: Expr, type2: VarType,
 
 class VectorOutputType(OutputType):
     name: VarName  # This has VarName type instead of Expr type becuase it will be subscripted.
-    type: VarType
+    type: Optional[VarType]
     subscripted_name: str  # TODO: remove this variable. This has a string like "a[i]", but carrying source code is not responsibility of this class.
     counter_name: VarName
     print_size: bool
     print_newline_after_size: bool
     print_newline_after_item: bool
 
-    def __init__(self, *, name: VarName, type: VarType, subscripted_name: str, counter_name: VarName, print_size: bool, print_newline_after_size: bool, print_newline_after_item: bool):
+    def __init__(self, *, name: VarName, type: Optional[VarType], subscripted_name: str, counter_name: VarName, print_size: bool, print_newline_after_size: bool, print_newline_after_item: bool):
         self.name = name
         self.type = type
         self.subscripted_name = subscripted_name
diff --git a/onlinejudge_template_resources/template/main.cpp b/onlinejudge_template_resources/template/main.cpp
index 4d6d210..bf10720 100644
--- a/onlinejudge_template_resources/template/main.cpp
+++ b/onlinejudge_template_resources/template/main.cpp
@@ -13,7 +13,6 @@
 <%
     logger = getLogger(__name__)
     data["config"]["rep_macro"] = "REP"
-    data["config"]["using_namespace_std"] = True
     data["config"]["long_long_int"] = "int64_t"
     if platform.system() == "Linux" and "clang" not in os.environ.get("CXX", "g++"):
         include = "#include <bits/stdc++.h>"
@@ -62,7 +61,6 @@ class ${topcoder.class_name(data)} {
 int main() {
     std::ios::sync_with_stdio(false);
     std::cin.tie(nullptr);
-    constexpr char endl = '\n';
 ${cplusplus.read_input(data)}
     auto ${cplusplus.return_value(data)} = ${solve_function}(${cplusplus.actual_arguments(data)});
 ${cplusplus.write_output(data)}


Test patch:
diff --git a/tests/analyzer_match.py b/tests/analyzer_match.py
new file mode 100644
index 0000000..87cfb8c
--- /dev/null
+++ b/tests/analyzer_match.py
@@ -0,0 +1,46 @@
+import textwrap
+import unittest
+
+import onlinejudge_template.analyzer.match as analyzer
+from onlinejudge_template.types import *
+
+
+class TestMinimumTree(unittest.TestCase):
+    def test_simple(self) -> None:
+        node = SequenceNode(items=[
+            ItemNode(indices=[], name='testcases'),
+            NewlineNode(),
+            LoopNode(name='i', size='testcases', body=SequenceNode(items=[
+                ItemNode(indices=['i'], name='a'),
+                NewlineNode(),
+                LoopNode(body=ItemNode(indices=['i', 'j'], name='b'), name='j', size='a_i'),
+                NewlineNode(),
+            ])),
+        ])
+        data = textwrap.dedent("""\
+        3
+        5
+        5 3 2 1 4
+        6
+        2 2 2 2 2 2
+        2
+        2 1
+        """)
+        variables = [
+            VarDecl(name=VarName('testcases'), type=None, dims=[], bases=[], depending=set()),
+            VarDecl(name=VarName('a'), type=None, dims=[Expr('testcases')], bases=[Expr('0')], depending={VarName('testcases')}),
+            VarDecl(name=VarName('b'), type=None, dims=[Expr('testcases'), Expr('a_i')], bases=[Expr('0'), Expr('0')], depending={VarName('testcases')}),
+        ]
+
+        expected: Dict[str, Any] = {
+            'testcases': {
+                (): 3
+            },
+            'a': {(i, ): a_i
+                  for (i, a_i) in enumerate([5, 6, 2])},
+            'b': {(i, j): b_i_j
+                  for i, b_i in enumerate([[5, 3, 2, 1, 4], [2, 2, 2, 2, 2, 2], [2, 1]]) for j, b_i_j in enumerate(b_i)},
+        }
+
+        actual = analyzer.match_format(node=node, data=data, variables={decl.name: decl for decl in variables})
+        self.assertEqual(actual, expected)
diff --git a/tests/analyzer_minimum_tree.py b/tests/analyzer_minimum_tree.py
index 33e93a3..4bd3283 100644
--- a/tests/analyzer_minimum_tree.py
+++ b/tests/analyzer_minimum_tree.py
@@ -190,3 +190,30 @@ def test_atcoder_agc028_f(self) -> None:
 
         actual = analyzer.construct_minimum_input_format_tree(instances=instances)
         self.assertEqual(str(actual), str(expected))
+
+    def test_multiple_test_cases(self) -> None:
+        instances = [
+            textwrap.dedent("""\
+            3
+            5
+            5 3 2 1 4
+            6
+            2 2 2 2 2 2
+            2
+            2 1
+            """),
+        ]
+        expected = SequenceNode(items=[
+            ItemNode(name='testcases'),
+            NewlineNode(),
+            LoopNode(size='testcases', name='i', body=SequenceNode(items=[
+                ItemNode(name='a', indices=['i']),
+                NewlineNode(),
+                LoopNode(size='a_i', name='j', body=ItemNode(name='b', indices=['i', 'j'])),
+                NewlineNode(),
+            ])),
+        ])
+
+        actual = analyzer.construct_minimum_input_format_tree(instances=instances, multiple_test_cases=True)
+        print(actual)
+        self.assertEqual(str(actual), str(expected))