2016 North American Invitational Programming Contest-J Whiteboard(区间交)

传送门:http://codeforces.com/gym/101002

题意:有一个n*m个画板,起始位置为(n,1),有q条指令,每条指令表示向上下左右一个方向走cnt步,每走一步花费1秒,每走到一个格子就会将格子染黑,现在给出目标图形,并且可以选择一段区间[L,R]使得在这段时间内走过的格子会变白,问这段区间L最小为多少,R最大为多少?

题解:对于目标图形,假设某个格子坐标是(x,y),走到这个格子的最后时间为time:

当mp[x][y]=='#'时,那么L>time

当mp[x][y]=='.'时,那么R<=time

只要按时间从后往前,找到每个格子被走到的最后时间,用来更新[L,R]即可

#include
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define x first
#define y second
#define rep(i,a,b) for(int i=(a);i<(b);++i)
#define per(i,a,b) for(int i=(a)-1;i>=(b);--i)
#define fuck(x) cout<<'['<<#x<<' '<<(x)<<']'< VI;
typedef pair pii;
typedef unsigned int ui;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int mod = 175781251;
const int MX = 1e6 + 5;
char str[2 * MX];
int n, m;
setsx[MX], sy[MX];
char get(int x, int y) {
    return str[x * m + y];
}
int to[][2] = {1, 0, 0, 1, 0, -1, -1, 0};
int op(char ch) {
    if(ch == 'd') return 0;
    if(ch == 'r') return 1;
    if(ch == 'l') return 2;
    return 3;
}
void solve(set& s, int now, int l, int r, ll last, ll& L, ll& R, int mark) {
    set::iterator it = s.lower_bound(min(l, r));
    for(; it != s.end() && *it <= max(l, r);) {
        char ch = mark ? get(*it, now) : get(now, *it);
        if(mark) sx[*it].erase(now);
        else sy[*it].erase(now);
        if(ch == '#') L = max(L, last - abs(*it - l));
        else R = min(R, last - abs(*it - l) - 1);
        s.erase(it++);
    }
}
int t[MX], c[MX];
int main() {
#ifdef local
    freopen("in.txt", "r", stdin);
#endif // local
    int q; cin >> n >> m >> q;
    rep(i, 1, n + 1) scanf("%s", str + i * m + 1);
    rep(i, 1, n + 1) rep(j, 1, m + 1) {
        sx[i].insert(j);
        sy[j].insert(i);
    }
    char s[10];
    int cx = n, cy = 1;
    ll cnt = 1;
    rep(i, 0, q) {
        scanf("%s%d", s, &c[i]);
        t[i] = op(s[0]);
        cx += to[t[i]][0] * c[i];
        cy += to[t[i]][1] * c[i];
        cnt += c[i];
    }
    ll L = 0, R = cnt;
    per(i, q, 0) {
        int tp = 3 - t[i];
        int nx = cx + to[tp][0] * c[i], ny = cy + to[tp][1] * c[i];
        if(tp == 0 || tp == 3) solve(sy[cy], cy, cx, nx, cnt, L, R, 1);
        else solve(sx[cx], cx, cy, ny, cnt, L, R, 0);
        cnt -= c[i];
        cx = nx;
        cy = ny;
    }
    int flag = 1;
    for(int i = 1; i <= n; i++) {
        for(int y : sx[i]) {
            if(get(i, y) == '#') L = R + 1;
        }
    }
    if(L <= R) printf("%lld %lld\n", L, R);
    else puts("-1 -1");
    return 0;
}

 

你可能感兴趣的:(贪心,思维题)