1. 程式人生 > >Good Bye 2015 F - New Year and Cleaning

Good Bye 2015 F - New Year and Cleaning

first sca 線性復雜 def int 復雜 main 線段 include

F - New Year and Cleaning

這題簡直是喪心病狂折磨王。。

思路:容易想到這樣一個轉換,把整個矩形一起移動,矩形移出去的時候相當於一行或者一列。

為了優化找到下一個消去的點,我先把原數組擴大兩倍,用了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; } /* */

Good Bye 2015 F - New Year and Cleaning