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<bits/stdc++.h>
#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)<<']'<<endl
#define clr(a,b) memset(a,b,sizeof(a))
#define cp(a,b) memcpy(a,b,sizeof(b))
#define eps 1e-10
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> VI;
typedef pair<int, int> 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;
set<int>sx[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<int>& s, int now, int l, int r, ll last, ll& L, ll& R, int mark) {
    set<int>::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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章