P6704 [COCI2010-2011#7] GITARA

这是一个关于计算外星人弹奏吉他时,根据给定的旋律和弦段信息,确定手指最小运动次数的问题。通过维护每根弦的状态,使用栈来跟踪按下的段数,并在需要时进行调整,从而找出最小的手指运动次数。题目提供了输入输出样例,以及数据规模和约束。
摘要由CSDN通过智能技术生成

题目背景

Darko 有一个想象的外星朋友,他有十亿根手指。外星人快速拿起吉他,在网上找到一段简单的旋律并开始弹奏。

这个吉他像寻常一样有六根弦,令其用 111 到 666 表示。每根弦被分成 PPP 段,令其用 111 到 PPP 表示。

旋律是一串的音调,每一个音调都是由按下特定的一根弦上的一段而产生的(如按第 444 弦第 888 段)。如果在一根弦上同时按在几段上,产生的音调是段数最大的那一段所能产生的音调。

例:对于第 333 根弦,第 555 段已经被按,若你要弹出第 777 段对应音调,只需把按住第 777 段,而不需放开第 555 段,因为只有最后的一段才会影响该弦产生的音调(在这个例子中是第 777 段)。类似,如果现在你要弹出第 222 段对应音调,你必须把第 555 段和第 777 段都释放。

请你编写一个程序,计算外星人在弹出给定的旋律情况下,手指运动的最小次数。
题目描述

你有一个 6×P6 \times P6×P 的矩阵 AAA,初始状态皆为 000。

对于所有要求 (i,j)(i,j)(i,j)

你需要满足要求:

此时 Ai,jA_{i,j}Ai,j​ 状态为 111。

对于 Ai,j+k(k>0)A_{i,j+k} (k>0)Ai,j+k​(k>0) 状态为 000。

你在满足要求的情况下需要求状态转换最小次数。
输入格式

第一行包含两个正整数 nnn ,PPP。它们分别指旋律中音调的数量及每根弦的段数。

下面的 nnn 行每行两个正整数 iii ,jjj,分别表示能弹出对应音调的位置——弦号和段号,其为外星人弹奏的顺序。
输出格式

一个非负整数表示外星人手指运动次数最小值。
输入输出样例
输入 #1

5 15
2 8
2 10
2 12
2 10
2 5

输出 #1

7

输入 #2

7 15
1 5
2 3
2 5
2 7
2 4
1 5
1 3

输出 #2

9

说明/提示
样例 1 解释

所有的音调都是由第二根弦产生的。首先按顺序按 888 101010 121212 (count=3count=3count=3)。然后释放第 121212 段(count=4count=4count=4)。最后,按下第 555 段,释放第 888 101010 段 (count=7count=7count=7)。
样例 2 解释

对于每个操作,分别需要 111 111 111 111 333 000 222 次手指运动。
数据规模及约定

按下或释放一段弦各计一次手指运动。弹弦不算手指的移动,而是一个弹吉他的动作。(指你不需要管他怎么弹的,只需要按就是啦,说不定他可以用超能力呀)

对于 100%100%100% 的数据 n≤5×105n \le 5 \times 10^5n≤5×105 ,2≤P≤3×1052 \le P \le 3 \times 10^52≤P≤3×105
说明

本题满分 707070 分。

译自 COCI2010-2011 CONTEST #7 T3 GITARA

#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
using namespace std;

int main() {
    vector< stack<int> > a;
    int x,y;
    cin>>x>>y;
    int cao_zuo=0;
    for(int i=0;i<=6;i++){
        stack<int> linshi;
        linshi.push(-1);
        a.push_back(linshi);
    }
    for(int i=0;i<x;i++){
        int xian,duan;
        cin>>xian>>duan;
        if(a.at(xian).top()<duan &duan<=y){
            a.at(xian).push(duan);
            cao_zuo++;
        }else if(a.at(xian).top()>duan ){
            while (a.at(xian).top()>duan & a.at(xian).top()>-1){
                a.at(xian).pop();
                cao_zuo++;
            }
            if(a.at(xian).top()!=duan){
                a.at(xian).push(duan);
                cao_zuo++;
            }
        } else {

        }
    }
    cout<<cao_zuo<<endl;
    return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值