Codeforces Good Bye 2017 F - New Year and Rainbow Roads

news/2024/7/11 4:58:44 标签: codeforces, , 贪心

一、如果升序中没有G颜色点:
那么我们找到第一个B颜色点prb(prev-blue)和最后一个B颜色点sub(succ-blue),和第一个R颜色点prr(prev-red)和最后一个R颜色点suc(succ-red),最优的方案是:

cost=xsubxprb+xsurxprr

如果某个颜色也不存在,则记Δx=0。

二、考虑升序中G颜色点对的划分:
无非几种情况:

[...]G[...]GG[]G[...]

①第一个G前还有其他点,比如说这样。
R1B1B2R2B3.........RiBkG

那么我们这么连接即可:
R1R2...B1B2...Ri|G|Bk

②两个G颜色点之间有其他元素
G1R1B1B2R2.........RiBkG2

那么我们有两种连接的方法:
Ⅰ.
R1|G1|B1......Ri|G2|Bk

R与R相连,B与B相连
Ⅱ.
R1|G1|B1...Rr Rr+1......Bb Bb+1...Ri|G2|Bk

将中间某两个点之间的边去掉,并把G 1和G 2连起来。
我们把最大的边剪掉。
对于Ⅰ和Ⅱ两种情况,取较小的cost即可。
③两个G颜色点之间没有其他元素
将G1和G2连接即可。
④最后一个G后还有其他点,仿照①即可。
上面基本上就是全部的思路,基于贪心

#include <cstdio>
#include <queue>
using namespace std;
queue<int> is,b;char geto[5];
int m[300005];bool mb[300005],nb=true,nr=true,fb,fr;
int main(){
    int i=0,n,pre,suc,sub,sur,prb,prr;double cost=0,mxb,mxr;
    scanf("%d",&n);
    for(int j=0;j<n;j++){
        scanf("%d%s",&m[j],geto);
        if(geto[0]=='G')is.push(j);
        if(geto[0]=='B')mb[j]=true;
    }
    if(is.empty()){
        prb=prr=0;sub=sur=n-1;
        while(prb<n){if(mb[prb])break;prb++;}
        while(prr<n){if(!mb[prr])break;prr++;}
        if(prb!=n-1)while(sub>=0){if(mb[sub])break;sub--;}
        if(prr!=n-1)while(sur>=0){if(!mb[sur])break;sur--;}
        cost+=m[sub]-m[prb]+m[sur]-m[prr];
    }else{
        suc=is.front();is.pop();
        while(i<suc){
            if(mb[i]&&nb)cost+=m[suc]-m[i],nb=false;
            if(!mb[i]&&nr)cost+=m[suc]-m[i],nr=false;
            i++;
        }
        for(i++;i<n;i++){
            nb=nr=false;fb=fr=true;mxb=mxr=-1;
            pre=suc;if(!is.empty()){suc=is.front();is.pop();}

            if(pre==suc){
                i=n-1;
                while(i>pre){
                    if(mb[i]&&!nb)cost+=m[i]-m[pre],nb=true;
                    if(!mb[i]&&!nr)cost+=m[i]-m[pre],nr=true;
                    i--;
                }
                break;
            }else{
                sub=prb=sur=prr=pre;
                while(i<suc){
                    if(mb[i]){
                        sub=i;nb=true;
                        if(m[sub]-m[prb]>mxb)mxb=m[sub]-m[prb];
                        prb=sub;
                    }else{
                        sur=i;nr=true;
                        if(m[sur]-m[prr]>mxr)mxr=m[sur]-m[prr];
                        prr=sur;
                    }
                    i++;
                }
                if(nb||nr){
                    if(sub!=pre)mxb=max(mxb,(double)m[suc]-m[sub]);
                    if(sur!=pre)mxr=max(mxr,(double)m[suc]-m[sur]);
                    if(mxr==-1)cost+=((m[suc]-m[pre])<<1)-mxb;
                    else if(mxb==-1)cost+=((m[suc]-m[pre])<<1)-mxr;
                    else cost+=((m[suc]-m[pre])<<1)+min(0.0,m[suc]-m[pre]-mxb-mxr);
                }else cost+=m[suc]-m[pre];
            }
        }
    }
    printf("%.0lf",cost);
}

http://www.niftyadmin.cn/n/1247304.html

相关文章

[练习]自己写的C语言链表模板 ver 1.0

#include <stdio.h> #include <stdlib.h> //定义布尔数值 true false #define true 1 #define false 0 //定义错误类型 wrong #define wrong 0x7fffffff typedef int boolean;//定义布尔类型 typedef struct Node *list,*position; struct Node{int data;//数据…

洛谷P1000 超级玛丽

想想那时候我还真是无聊呢&#xff0c;好吧现在也很无聊w #include<cstdio> using namespace std; int main() {printf(" ********\n");printf(" ************\n");printf(" ####....#.\n");…

Ubuntu 安装git

安装的方法有两种&#xff0c;一种直接是通过ubuntu的APT安装&#xff0c;这种方法最简便&#xff0c;缺点是版本可能不是最新的。所有还有另一种方法是下载源码进行安装&#xff0c;这种能安装到想要的版本。这里只说第一种&#xff1a; 步骤&#xff1a; sudo apt-get updat…

LeetCode50天刷题计划第二季(Day 10 —从前序与中序遍历序列构造二叉树(20.00-20.40)从中序与后序遍历序列构造二叉树(20.40-21.00)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、题目从前序与中序遍历序列构造二叉树示例提示二、思路三、代码四、题目从中序与后序遍历序列构造二叉树示例提示五、思路六、代码前言 今天好冷啊 感觉要99…

洛谷P1002 过河卒

貌似是我做的第一道dp题&#xff0c;hh岁月如水&#xff0c;很简单就不说啥了 #include <cstdio> long long step[25][25]; bool map[25][25]; int main(){int b1,b2,m1,m2;scanf("%d%d%d%d",&b1,&b2,&m1,&m2);map[m1][m2]map[m1-1][m22]map[…

ubuntu 16.04LTS 下Code::Blocks 16.01 安装

http://blog.csdn.net/left_coast/article/details/52159762 ubuntu 16.04LTS 下Code::Blocks 16.01 安装 Code::Blocks 是一个开放源码的全功能的跨平台C/C集成开发环境。 Code::Blocks是开放源码软件。Code::Blocks由纯粹的C语言开发完成&#xff0c;它使用了著名的图形界面…

LeetCode50天刷题计划第二季(Day 11 — 将有序数组转换为二叉搜索树(12.00-12.40)有序链表转换二叉搜索树(12.20-12.40)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、题目将有序数组转换为二叉搜索树示例提示二、思路三、代码四、题目有序链表转换二叉搜索树示例提示:五、思路六、代码前言 昨天没写 今天还债 一、题目 将…