COCI2015/2016 Contest#4 F Solution

在森林覆盖的Endor月球上,据吉尼斯世界纪录记载,有银河系中最长的棍子。棍子上有N只欢快的变色龙,它们以1 m/s的速度向左右两个方向匀速移动,并且每只变色龙都有K种可能的颜色之一。当两只变色龙相撞时,它们会180度转向并交换颜色。问题要求计算每种颜色的变色龙离开棍子前的总行程。解决方案是将向右移动的变色龙视为静止,让向左的以两倍速度移动,通过一次扫描计算每个颜色的行程。注意在撞到最后一只静止的变色龙后的行程也不能忽略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description
On the forest-filled moon of Endor there is, if we are to believe the Guinness Book of Records, the
longest stick in the whole galaxy. On that stick of L meters in length there are N cheerful chameleons.

Each chameleon is moving along the stick with constant speed of 1 m/s in one of two possible directions(left or right) and is colored in one of the possible K colors.

It is known that the chameleons of Endor worship the ancient ant laws that dictate that the walk
along the stick must be continued until the end of the stick is reached (which means getting off it),and when a collision with another chameleon takes place, you must turn 180 degrees and continue
the walk in the opposite direction. Additionally, after a chameleon colored in a moving to the left
collides with a chameleon colored in b moving to the right, the chameleon moving to the left before the collision takes the color of the chameleon moving to the right before the collision (so, color b), while the chameleon moving to the right before the collision takes a new color (a + b) mod K.

If you are given the initial positions, colors and directions of movement of all the chameleons, for each color determine the total trip taken by the chameleons in that color before getting off the stick.

Solution
这题比上题(戳这)要简单数倍==亏它是F题。
一看就知道是一道弹性形变。
向右的会一条道到黑我们把他们视为静止。
然后让向左的以两倍的速度向左移动。
这样的话我们向左扫一发即可。
有个坑就是在到达最后一个静止的点之前的差是不变的,但是到了最后一个点之后还要走一段路,这个不可以丢。
之前就是因为这里写错了导致没A==

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int M=1e5+5;
typedef double db;
int n,k,L,post[M*20],run[M*20],last[50];
db sum[M],s[M],tp[M];
int cnt[M],tmp[M];
inline int Mod(int a){return a>=k?a-k:a;}
int main(){
    cin>>n>>k>>L;
    char opt[10];
    memset(post,-1,sizeof(post));
    memset(run,-1,sizeof(run));
    memset(last,-1,sizeof(last));
    int st=-1;
    int p[10];
    for(int i=1,dis,clr;i<=n;++i){
        scanf("%d %d %s",&dis,&clr,opt);
        switch(opt[0]){
            case('D'):
                post[dis]=clr;
                sum[clr]+=L-dis;
                if(st==-1)st=dis;
                break;
            case('L'):
                if(st==-1)sum[clr]+=dis;
                run[dis]=clr;
                break;
        }
    }
    for(int i=L;i>=st;--i){
        for(int c=0;c<k;++c)
            sum[c]+=0.5*cnt[c];
        if(~run[i]){
            ++cnt[run[i]];
            s[run[i]]+=(double)(st+i)/2.0;
        }
        if(~post[i]){
            for(int c=0;c<k;++c){
                tmp[Mod(c+post[i])]=cnt[c];
                tp[Mod(c+post[i])]=s[c];
            }
            for(int c=0;c<k;++c){
                cnt[c]=tmp[c];tmp[c]=0;
                s[c]=tp[c];tp[c]=0;
            }
        }//变色 
    }
    for(int c=0;c<k;++c)
        sum[c]+=(double)s[c];
    for(int i=0;i<k;++i)
        printf("%.1lf\n",(double)sum[i]);
    return 0;
}
/**************************************************************
    Problem: 1791
    User: bblss123
    Language: C++
    Result: 正确
    Time:200 ms
    Memory:20448 kb
****************************************************************/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值