Codeforces Good Bye 2017 F - New Year and Rainbow Roads
2017-12-30 13:26
411 查看
一、如果升序中没有G颜色点:
那么我们找到第一个B颜色点prb(prev-blue)和最后一个B颜色点sub(succ-blue),和第一个R颜色点prr(prev-red)和最后一个R颜色点suc(succ-red),最优的方案是:
cost=xsub−xprb+xsur−xprr
如果某个颜色也不存在,则记Δx=0。
二、考虑升序中G颜色点对图的划分:
无非几种情况:
[...]①G[...]②GG[]③G[...]④
①第一个G前还有其他点,比如说这样。
R1B1B2R2B3.........RiBkG
那么我们这么连接即可:
R1−R2−...−B1−B2−...−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
将中间某两个点之间的边去掉,并把G1和G2连起来。
我们把最大的边剪掉。
对于Ⅰ和Ⅱ两种情况,取较小的cost即可。
③两个G颜色点之间没有其他元素
将G1和G2连接即可。
④最后一个G后还有其他点,仿照①即可。
上面基本上就是全部的思路,基于贪心。
那么我们找到第一个B颜色点prb(prev-blue)和最后一个B颜色点sub(succ-blue),和第一个R颜色点prr(prev-red)和最后一个R颜色点suc(succ-red),最优的方案是:
cost=xsub−xprb+xsur−xprr
如果某个颜色也不存在,则记Δx=0。
二、考虑升序中G颜色点对图的划分:
无非几种情况:
[...]①G[...]②GG[]③G[...]④
①第一个G前还有其他点,比如说这样。
R1B1B2R2B3.........RiBkG
那么我们这么连接即可:
R1−R2−...−B1−B2−...−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
将中间某两个点之间的边去掉,并把G1和G2连起来。
我们把最大的边剪掉。
对于Ⅰ和Ⅱ两种情况,取较小的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); }
相关文章推荐
- Codeforces Good Bye 2017: F. New Year and Rainbow Roads(模拟)
- Codeforces Good Bye 2017 908F - New Year and Rainbow Roads 贪心+模拟
- Good Bye 2017 F-New Year and Rainbow Roads
- Codeforces Good Bye 2017 C - New Year and Curling
- Codeforces-Good Bye 2017 C. New Year and Curling(计算几何)
- Codeforces Good Bye 2017 C. New Year and Curling(模拟水题)
- Codeforces 908F - New Year and Rainbow Roads 【脑洞】
- Codeforces-Good Bye 2017 B. New Year and Buggy Bot(模拟)
- Codeforces Good Bye 2017 D. New Year and Arbitrary Arrangement
- Codeforces Good Bye 2017 A - New Year and Counting Cards
- Codeforces Good Bye 2017 B - New Year and Buggy Bot
- Codeforces Good Bye 2016 D. New Year and Fireworks(bfs/dfs)
- 【Good Bye 2017 B】 New Year and Buggy Bot
- Codeforces Good Bye 2015 A. New Year and Days
- 【Good Bye 2017 C】 New Year and Curling
- Codeforces Good Bye 2015 D. New Year and Ancient Prophecy DP
- Codeforces Good Bye 2015 C. New Year and Domino 前缀和
- Good Bye 2017 D. New Year and Arbitrary Arrangement
- Good Bye 2017 D. New Year and Arbitrary Arrangement
- Codeforces Good Bye 2015 C. New Year and Domino (预处理)