HGOI 20200731
7月的最后一天!
不得不说这套题部分分是真的多
T1 马里奥
二分+BFS
没有技术含量
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define per(i, a, b) for (int i = a; i >= b; i--)
#define siz(a) (int)a.size()
#define pb push_back
#define mp make_pair
#define ll long long
#define fi first
#define se second
const int N = 1010 ;
int n, m, ex, ey, ans ;
int a[N][N], vis[N][N] ;
queue <pair<int, int> > q ;
bool check(int stp) {
// cout << stp << endl ;
memset(vis, 0, sizeof(vis)) ;
while (!q.empty()) q.pop() ;
q.push(mp(n, 1)) ; vis[n][1] = 1 ;
while (!q.empty()) {
int x = q.front().fi, y = q.front().se ; q.pop() ;
// cout << " * " << x << " " << y << endl ;
if (x == ex && y == ey) return true ;
if (y - 1 > 0 && !vis[x][y - 1] && a[x][y - 1]) {
vis[x][y - 1] = 1 ;
q.push(mp(x, y - 1)) ;
}
if (y + 1 <= m && !vis[x][y + 1] && a[x][y + 1]) {
vis[x][y + 1] = 1 ;
q.push(mp(x, y + 1)) ;
}
rep(k, 1, stp) {
if (x - k > 0 && !vis[x - k][y] && a[x - k][y]) {
vis[x - k][y] = 1 ;
q.push(mp(x - k, y)) ;
}
if (x + k <= n && !vis[x + k][y] && a[x + k][y]) {
vis[x + k][y] = 1 ;
q.push(mp(x + k, y)) ;
}
}
}
return false ;
}
signed main() {
freopen("mario.in", "r", stdin) ;
freopen("mario.out", "w", stdout) ;
scanf("%d%d", &n, &m) ;
rep(i, 1, n) {
string s ; cin >> s ;
rep(j, 1, m) a[i][j] = (s[j - 1] == '#' ? 1 : 0) ;
}
// rep(i, 1, n) {
// rep(j, 1, m) cout << a[i][j] ;
// cout << endl ;
// }
scanf("%d%d", &ex, &ey) ;
int l = 0, r = n ;
while (l <= r) {
// cout << l << " " << r << endl ;
int mid = (l + r) >> 1 ;
if (check(mid)) ans = mid, r = mid - 1 ;
else l = mid + 1 ;
}
printf("%d\n", ans) ;
return 0 ;
}
T2 祭司
可以发现
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define per(i, a, b) for (int i = a; i >= b; i--)
#define siz(a) (int)a.size()
#define pb push_back
#define mp make_pair
#define ll long long
#define fi first
#define se second
const int N = 210 ;
const int iinf = 0x3f3f3f3f ;
struct rec {
int l, r ;
} a[N] ;
int n ;
bool f[N * N] ;
signed main() {
scanf("%d", &n) ;
int Sum1 = 0, Sum2 = 0 ;
rep(i, 1, n) {
scanf("%d%d", &a[i].l, &a[i].r) ;
Sum1 += a[i].l ; Sum2 += a[i].r ;
}
memset(f, 0, sizeof(f)) ;
f[0] = 1 ;
rep(i, 1, n)
per(j, 40000, a[i].l + a[i].r)
f[j] |= f[j - a[i].l - a[i].r] ;
int ans = iinf ;
rep(i, 0, 40000) {
if (!f[i]) continue ;
ans = min(ans, max(abs(Sum1 - i), abs(Sum2 - i))) ;
}
printf("%d\n", ans) ;
return 0;
}
T3 AK
分块
发现一个数进行一些平方后就会不变,大约进行30次左右
这样就可以暴力
那些操作了过多次的就不管
对后面的进行修改即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define per(i, a, b) for (int i = a; i >= b; i--)
#define siz(a) (int)a.size()
#define pb push_back
#define mp make_pair
#define ll long long
#define fi first
#define se second
const int lim = 30 ;
const int N = 66010 ;
const int mod = 2305843008676823040 ;
int n, m, num, len ;
int a[N], bl[N], l[N], r[N], sum[N], cnt[N], fa[N] ;
int mul(int a, int b) {
int res = 0 ;
while (b) {
if (b & 1) res = (res + a) % mod ;
a = (a << 1) % mod ;
b >>= 1 ;
}
return res % mod ;
}
void build() {
len = sqrt(n) ;
num = (n - 1) / len + 1 ;
rep(i, 1, n) bl[i] = (i - 1) / len + 1 ;
rep(i, 1, num) l[i] = len * (i - 1) + 1, r[i] = len * i ;
r[num] = n ;
rep(i, 1, n) sum[bl[i]] = (sum[bl[i]] + a[i]) % mod ;
memset(cnt, 0, sizeof(cnt)) ;
}
int find(int x) {
return fa[x] == x ? x : fa[x] = find(fa[x]) ;
}
int query(int ql, int qr) {
int L = bl[ql], R = bl[qr], ans = 0 ;
if (L == R) {
rep(i, ql, qr) ans = (ans + a[i]) % mod ;
return ans ;
} else {
rep(i, ql, r[bl[ql]]) ans = (ans + a[i]) % mod ;
rep(i, bl[ql] + 1, bl[qr] - 1) ans = (ans + sum[i]) % mod ;
rep(i, l[bl[qr]], qr) ans = (ans + a[i]) % mod ;
return ans ;
}
}
void update(int ql, int qr) {
for (int i = ql; i <= qr; i = find(i + 1)) {
if (i > qr) break ;
cnt[i]++ ;
sum[bl[i]] = (sum[bl[i]] - a[i] + mod) % mod ;
a[i] = mul(a[i], a[i]) % mod ;
sum[bl[i]] = (sum[bl[i]] + a[i]) % mod ;
if (cnt[i] > lim) fa[i] = find(i + 1) ;
}
}
signed main() {
freopen("ak.in", "r", stdin) ;
freopen("ak.out", "w", stdout) ;
scanf("%lld%lld", &n, &m) ;
rep(i, 1, n) scanf("%lld", &a[i]) ;
build() ;
rep(i, 1, n + 1) fa[i] = i ;
while (m--) {
int ql, qr ; scanf("%lld%lld", &ql, &qr) ;
printf("%lld\n", query(ql, qr)) ;
update(ql, qr) ;
}
return 0 ;
}
加油ヾ(◍°∇°◍)ノ゙