这题简直是丧心病狂折磨王。。
思路:容易想到这样一个转换,把整个矩形一起移动,矩形移出去的时候相当于一行或者一列。
为了优化找到下一个消去的点,我先把原数组扩大两倍,用了st表加二分去找,然后就MLE, 我又换了
线段树TLE,最后不把数组扩大两倍ST表+二分过的。。
每次消去的点都是不变的,所以可以做到线性复杂度。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PII pair<int, int> #define PLI pair<LL, int> #define ull unsigned long long using namespace std; const int N = 5e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; int k, n, m, X[N], Y[N], Log[N]; char s[N]; struct ST { int dp[N][20],ty; void build(int n, int b[], int _ty) { ty = _ty; for(int i = 1; i <= n; i++) dp[i][0] = ty * b[i]; for(int j = 1; j <= Log[n]; j++) for(int i = 1; i+(1<<j)-1 <= n; i++) dp[i][j] = max(dp[i][j-1], dp[i+(1<<(j-1))][j-1]); } int query(int x, int y) { int k = Log[y - x + 1]; return ty * max(dp[x][k], dp[y-(1<<k)+1][k]); } } mxx, mnx, mxy, mny; void walk(int &x, int &y, char c) { if(c == 'R') y++; else if(c == 'L') y--; else if(c == 'U') x--; else x++; } bool check(int l, int r, int x, int y, int lenr, int lenc) { int mxX = mxx.query(l, r) - X[l-1]; int mnX = mnx.query(l, r) - X[l-1]; int mxY = mxy.query(l, r) - Y[l-1]; int mnY = mny.query(l, r) - Y[l-1]; if(x+mxX+lenr > n || x+mnX < 0 || y+mxY+lenc > m || y+mnY < 0) return true; return false; } int main() { for(int i = -(Log[0]=-1); i < N; i++) Log[i] = Log[i - 1] + ((i & (i - 1)) == 0); scanf("%d%d%d%s", &k, &n, &m, s + 1); int x = 0, y = 0, L = 0, R = 0, D = 0, U = 0, p = 0; for(int i = 1; i <= k; i++) { walk(x, y, s[i]); L = min(L, y); R = max(R, y); U = min(U, x); D = max(D, x); } if(!x && !y) { if(R - L + 1 <= m && D - U + 1 <= n) { puts("-1"); return 0; } } x = 0, y = 0; for(int i = 1; i <= k; i++) { walk(x, y, s[i]); X[i] = x; Y[i] = y; } mxx.build(k, X, 1); mnx.build(k, X, -1); mxy.build(k, Y, 1); mny.build(k, Y, -1); x = 0, y = 0; int lenr = n, lenc = m; LL ans = 0, t = 0; while(lenr && lenc) { int l = p + 1, r = min(k, p + k), pos = -1; while(l <= r) { int mid = l + r >> 1; if(check(p + 1, mid, x, y, lenr, lenc)) r = mid - 1, pos = mid; else l = mid + 1; } if(pos != -1) { x += X[pos] - X[p]; y += Y[pos] - Y[p]; t = (t + pos - p) % mod; p = pos; if(s[p] == 'U') { lenr--; ans = (ans + 1ll*t*lenc) % mod; x = 0; } else if(s[p] == 'D') { lenr--; ans = (ans + 1ll*t*lenc) % mod; } else if(s[p] == 'L') { lenc--; ans = (ans + 1ll*t*lenr) % mod; y = 0; } else { lenc--; ans = (ans + 1ll*t*lenr) % mod; } if(p == k) p = 0; } else { x += X[k] - X[p]; y += Y[k] - Y[p]; t = (t + k - p) % mod; p = 0; } } printf("%lld\n", ans); return 0; } /* */