[Codeforces Round #310 DIV1C (CF555C)] Case of Chocolate

题意

给定一个 n×n 网格,网格上 i+jn+1(1i,jn) 的地方有巧克力,每次从对角线上某处开始吃,向 i 减少的方向或j减小的方向水平或竖直地吃,直到遇见没有巧克力的网格或走出边界。询问每次迟到的巧克力数。

题解

在不断地吃的过程中,会发现形成了一个个五边形或其退化,如下

C * * * * * *
*           *
*           *
*           *
*           *
*           B
*         *  
*       *    
* * * A

用set记录下来A点和C点即可完成询问和修改。

代码

/// by ztx
#include <cstdio>
#define Rep(i,l,r) for(i=(l);i<=(r);i++)
#define rep(i,l,r) for(i=(l);i< (r);i++)
typedef long long ll ;
int CH;
template <typename TP>inline void read(TP& ret) {
    ret = 0 ; while (CH=getchar() , CH<'!') ;
    while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
}
template <typename TP>inline void readc(TP& ret) {
    while (ret=getchar() , ret<'!') ;
    //while (CH=getchar() , CH>'!') ;
}

#include <algorithm>
#include <set>

#define  maxm  200010LL

struct Poi { int x, y; };
struct Pen {
    Poi A, C;
    bool operator < (const Pen&b) const { return A.x < b.A.x; }
};

std::set<Pen>S;
std::set<Pen>::iterator it;

int main() {
    int n, m, x, y, d;
    Poi A, C;
    read(n), read(m);
    S.insert((Pen){(Poi){0,n+1},(Poi){0,0}});
    S.insert((Pen){(Poi){n+1,0},(Poi){n+1,0}});
    while (m --> 0) {
        read(x), read(y), readc(d);
        it = S.lower_bound((Pen){(Poi){x,y}});
        if (it->A.x == x) { puts("0"); continue; }
        it -- ;
        if (d == 'U') {
            printf("%d\n", y-it->C.y);
            S.insert((Pen){(Poi){x,y},(Poi){x,it->C.y}});
        } else {
            printf("%d\n",x-it->C.x);
            A = it->A, C = it->C;
            S.erase(it);
            S.insert((Pen){A,(Poi){C.x,y}});
            S.insert((Pen){(Poi){x,y},C});
        }
    }
    getchar(),getchar();
    return 0;
}

/*
all can become this pentagon:
C * * * * * *
*           *
*           *
*           *
*           *
*           B
*         *  
*       *    
* * * A
record point A, C
and ordered by point A

initial
    0 1 2 . . n n+1
0   C * * * * * B
1   *         *
2   *       *
.   *     *
.   *   *      
n   * *
n+1 A

*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值