正睿 25 年省选联考 Day 18
正睿 25 年省选联考 Day 18
得分
| T1 | T2 | T3 | 总分 | 排名 |
|---|---|---|---|---|
| \(100\) | \(70\) | \(100\) | \(270\) | \(4/20\) |
题解
T1 province
送分题。设 \(dp(i,j)\) 表示将前 \(i\) 个城市划分成 \(j\) 个省的最小代价,转移为:
\[dp(i,j)=\min\{dp(k,j-1)+(h_i-h_{k+1})^2\}
\]
这是一个显然的斜率优化式子,拆开即可。可以用凸包 / 李超线段树维护之,注意如果用凸包的话横坐标 \(h_i\) 不保证单调,所以要用 set 或者 CDQ 分治。
#include <bits/stdc++.h>
#define il inline
#define int long long
#define ll __int128
using namespace std;
const int Maxn = 1e4 + 5;
const int Inf = 1e18;
template <typename T> il void chkmax(T &x, T y) {x = (x >= y ? x : y);}
template <typename T> il void chkmin(T &x, T y) {x = (x <= y ? x : y);}
template <typename T>
il void read(T &x) {
x = 0; char ch = getchar(); bool flg = 0;
for(; ch < '0' || ch > '9'; ch = getchar()) flg = (ch == '-');
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
flg ? x = -x : 0;
}
template <typename T>
il void write(T x, bool typ = 1) {
static short Stk[50], Top = 0;
x < 0 ? putchar('-'), x = -x : 0;
do Stk[++Top] = x % 10, x /= 10; while(x);
while(Top) putchar(Stk[Top--] | 48);
typ ? putchar('\n') : putchar(' ');
}
il void IOS() {ios::sync_with_stdio(0); cin.tie(0), cout.tie(0);}
il void File() {freopen("data.txt", "r", stdin); }
bool Beg;
int n, k, a[Maxn];
struct Point {
int x, y;
Point operator - (Point b) {return {x - b.x, y - b.y};}
ll operator * (Point b) {return (ll)x * b.y - (ll)y * b.x;}
int operator ()(int b) {return -x * b + y;}
};
vector <Point> con[105];
int dp[Maxn][105];
int calc(int j, int k) {
int l = 0, r = con[j - 1].size() - 2, res = con[j - 1].size() - 1;
while(l <= r) {
int mid = (l + r) >> 1;
int res1 = con[j - 1][mid](k);
int res2 = con[j - 1][mid + 1](k);
if(res1 < res2) res = mid, r = mid - 1;
else l = mid + 1;
}
return con[j - 1][res](k);
}
void insert(int j, Point p) {
while(con[j].size() > 1 && (p - con[j].back()) * (con[j].back() - con[j][con[j].size() - 2]) > 0) con[j].pop_back();
con[j].push_back(p);
}
struct node {
int i, val;
}p[Maxn];
void cdq(int l, int r) {
if(l == r) {
chkmin(dp[l][1], (a[l] - a[1]) * (a[l] - a[1])); return;
}
int mid = (l + r) >> 1;
cdq(l, mid);
sort(p + l, p + mid + 1, [](node x, node y){return x.val < y.val;});
for(int i = l; i <= mid; i++) {
int x = p[i].i;
for(int j = 1; j <= k; j++) {
insert(j, {2 * a[x + 1], dp[x][j] + a[x + 1] * a[x + 1]});
}
}
for(int i = mid + 1; i <= r; i++) {
for(int j = 1; j <= k; j++) {
if(!con[j - 1].size()) continue;
chkmin(dp[i][j], calc(j, a[i]) + a[i] * a[i]);
}
}
for(int i = 1; i <= k; i++) con[i].clear();
cdq(mid + 1, r);
}
bool End;
il void Usd() {cerr << (&Beg - &End) / 1024.0 / 1024.0 << "MB " << (double)clock() * 1000.0 / CLOCKS_PER_SEC << "ms\n"; }
signed main() {
read(n), read(k);
for(int i = 1; i <= n; i++) read(a[i]);
for(int i = 1; i <= n; i++) p[i] = {i, a[i + 1]};
for(int i = 0; i <= n; i++) for(int j = 0; j <= k; j++) dp[i][j] = Inf;
cdq(1, n);
write(dp[n][k]);
Usd();
return 0;
}
T2 matching
给一篇论文自己看:\(\text{Link}\),基本上没有什么改动。
#include <bits/stdc++.h>
#define il inline
using namespace std;
typedef long long ll;
const int Maxn = 100 + 5;
const int Inf = 2e9;
int Mod;
il int Add(int x, int y) {return x + y >= Mod ? x + y - Mod: x + y;} il void pls(int &x, int y) {x = Add(x, y);}
il int Del(int x, int y) {return x - y < 0 ? x - y + Mod : x - y;} il void sub(int &x, int y) {x = Del(x, y);}
il int qpow(int a, int b, int P = Mod) {int res = 1; for(; b; a = 1ll * a * a % P, b >>= 1) if(b & 1) res = 1ll * res * a % P; return res;}
il int Inv(int a) {return qpow(a, Mod - 2);}
template <typename T> il void chkmax(T &x, T y) {x = (x >= y ? x : y);}
template <typename T> il void chkmin(T &x, T y) {x = (x <= y ? x : y);}
template <typename T>
il void read(T &x) {
x = 0; char ch = getchar(); bool flg = 0;
for(; ch < '0' || ch > '9'; ch = getchar()) flg = (ch == '-');
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
flg ? x = -x : 0;
}
template <typename T>
il void write(T x, bool typ = 1) {
static short Stk[50], Top = 0;
x < 0 ? putchar('-'), x = -x : 0;
do Stk[++Top] = x % 10, x /= 10; while(x);
while(Top) putchar(Stk[Top--] | 48);
typ ? putchar('\n') : putchar(' ');
}
il void IOS() {ios::sync_with_stdio(0); cin.tie(0), cout.tie(0);}
il void File() {freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout);}
bool Beg;
int n, k, a[Maxn][Maxn];
int prim[] = {0, 2, 3, 5, 7, 11};
int MR(int x) {
if(x == 2) return 1;
int t = x - 1, k = 0;
while(!(t & 1)) t >>= 1, k++;
for(int i = 1; i <= 5; i++) {
if(x == prim[i]) return 1;
int a = qpow(prim[i] % x, t, x), nxt;
for(int j = 1; j <= k; j++) {
nxt = 1ll * a * a % x;
if(nxt == 1 && a != 1 && a != x - 1) return 0;
a = nxt;
}
if(a != 1) return 0;
}
return 1;
}
int getP() {
if(k == 1) return 1145141;
int ret = k * k * k * k + 1 % k;
do ret += k; while(!MR(ret));
return ret;
}
int fac[Maxn], tot;
int check(int g, int Mod) {
if(qpow(g, Mod - 1) != 1) return 0;
for(int i = 1; i <= tot; i++) {
if(qpow(g, (Mod - 1) / fac[i]) == 1) return 0;
}
return 1;
}
int getG() {
int phi = Mod - 1, tmp = phi;
for(int i = 2; i < tmp / i; i++) {
if(tmp % i == 0) fac[++tot] = i;
while(tmp % i == 0) tmp /= i;
}
if(tmp > 1) fac[++tot] = tmp;
for(int i = 1; i < Mod; i++) {
if(check(i, Mod)) return i;
}
}
mt19937 rnd(time(0));
int b[Maxn][Maxn], mat[Maxn][Maxn];
int Det() {
int ret = 1;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
if(mat[j][j] && j < i) continue;
if(mat[j][i]) {
swap(mat[i], mat[j]);
if(i != j) ret = 1ll * ret * (Mod - 1) % Mod;
break;
}
}
for(int j = 1; j <= n; j++) {
if(i != j) {
int inv = 1ll * mat[j][i] * Inv(mat[i][i]) % Mod;
for(int k = 1; k <= n; k++) sub(mat[j][k], 1ll * mat[i][k] * inv % Mod);
}
}
}
for(int i = 1; i <= n; i++) ret = 1ll * ret * mat[i][i] % Mod;
return ret;
}
bool End;
il void Usd() {cerr << (&Beg - &End) / 1024.0 / 1024.0 << "MB " << (double)clock() * 1000.0 / CLOCKS_PER_SEC << "ms\n"; }
int main() {
read(n), read(k);
for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) read(a[i][j]);
Mod = getP();
int g = getG(), p = qpow(g, (Mod - 1) / k);
for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) b[i][j] = rnd() % Mod;
int ans = 0;
for(int r = 0; r < k; r++) {
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
if(a[i][j] != -1) mat[i][j] = 1ll * b[i][j] * qpow(p, r * a[i][j]) % Mod;
else mat[i][j] = 0;
}
}
pls(ans, Det());
}
if(ans == 0) puts("No");
else puts("Yes");
Usd();
return 0;
}
T3 max
首先 \(\text{and}\) 和 \(\text{or}\) 操作的本质就是将某一位上的 \(1/0\) 全部改为 \(0/1\)。所以和上一场 T1 如出一辙,继续考虑颜色段均摊。我们在每一个节点处对每一位维护一个覆盖标记,表示这一位上是否要全部覆盖为 \(0/1\)。当我们要修改一个区间时,先找到区间的对应节点,然后向下递归,找到同色连续段;此时对于这个同色连续段,我们的操作实际上就相当于区间加 / 减 \(2^k\),打懒标记即可。
这样的话复杂度是 \(O((n+q)k\log n)\) 的,略微卡常即可通过。
#include <bits/stdc++.h>
#define il inline
using namespace std;
constexpr int Maxn = 2e5 + 5;
constexpr int Inf = 2e9;
template <typename T>
il void read(T &x) {
x = 0; char ch = getchar(); bool flg = 0;
for(; ch < '0' || ch > '9'; ch = getchar()) flg = (ch == '-');
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
flg ? x = -x : 0;
}
template <typename T>
il void write(T x, bool typ = 1) {
static short Stk[50], Top = 0;
x < 0 ? putchar('-'), x = -x : 0;
do Stk[++Top] = x % 10, x /= 10; while(x);
while(Top) putchar(Stk[Top--] | 48);
typ ? putchar('\n') : putchar(' ');
}
il void IOS() {ios::sync_with_stdio(0); cin.tie(0), cout.tie(0);}
il void File() {freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout);}
bool Beg;
int n, q, a[Maxn];
int pw[25];
constexpr int MX = 20;
namespace SGT {
struct node {
int sum[MX], cov[MX], tag, mx;
}t[Maxn << 2];
#define ls(p) (p << 1)
#define rs(p) (p << 1 | 1)
il void pushup(int p, int k) {
t[p].sum[k] = t[ls(p)].sum[k] + t[rs(p)].sum[k];
t[p].mx = max(t[ls(p)].mx, t[rs(p)].mx);
}
il void build(int p, int l, int r) {
for(int i = 0; i < MX; i++) t[p].cov[i] = -1;
if(l == r) {
for(int i = 0; i < MX; i++) t[p].sum[i] = (a[l] >> i) & 1;
t[p].mx = a[l]; return ;
}
int mid = (l + r) >> 1;
build(ls(p), l, mid), build(rs(p), mid + 1, r);
for(int i = 0; i < MX; i++) t[p].sum[i] = t[ls(p)].sum[i] + t[rs(p)].sum[i];
t[p].mx = max(t[ls(p)].mx, t[rs(p)].mx);
}
il void pushadd(int p, int l, int r, int k) {t[p].cov[k] = 1, t[p].sum[k] = r - l + 1;}
il void pushdel(int p, int k) {t[p].cov[k] = 0, t[p].sum[k] = 0;}
il void pushtag(int p, int k) {t[p].tag += k, t[p].mx += k;}
il void pushdown(int p, int l, int r, int k) {
int mid = (l + r) >> 1;
t[p].cov[k] == 1 ? pushadd(ls(p), l, mid, k), pushadd(rs(p), mid + 1, r, k) :
(t[p].cov[k] == 0 ? pushdel(ls(p), k), pushdel(rs(p), k) : void());
t[p].cov[k] = -1;
pushtag(ls(p), t[p].tag), pushtag(rs(p), t[p].tag), t[p].tag = 0;
}
il void pushdown1(int p, int l, int r) {
int mid = (l + r) >> 1;
for(int i = 0; i < MX; i++) {
t[p].cov[i] == 1 ? pushadd(ls(p), l, mid, i), pushadd(rs(p), mid + 1, r, i) :
(t[p].cov[i] == 0 ? pushdel(ls(p), i), pushdel(rs(p), i) : void());
t[p].cov[i] = -1;
}
pushtag(ls(p), t[p].tag), pushtag(rs(p), t[p].tag), t[p].tag = 0;
}
il void mdfdel(int p, int l, int r, int k) {
if(t[p].sum[k] == 0) return ;
if(t[p].sum[k] == r - l + 1) {
pushtag(p, -pw[k]); return ;
}
pushdown(p, l, r, k);
int mid = (l + r) >> 1;
mdfdel(ls(p), l, mid, k), mdfdel(rs(p), mid + 1, r, k);
pushup(p, k);
}
il void mdfand(int p, int l, int r, int pl, int pr, int k) {
if(pl <= l && r <= pr) {
mdfdel(p, l, r, k);
pushdel(p, k);
return ;
}
pushdown(p, l, r, k);
int mid = (l + r) >> 1;
if(pl <= mid) mdfand(ls(p), l, mid, pl, pr, k);
if(pr > mid) mdfand(rs(p), mid + 1, r, pl, pr, k);
pushup(p, k);
}
il void mdfadd(int p, int l, int r, int k) {
if(t[p].sum[k] == r - l + 1) return ;
if(t[p].sum[k] == 0) {
pushtag(p, pw[k]); return ;
}
pushdown(p, l, r, k);
int mid = (l + r) >> 1;
mdfadd(ls(p), l, mid, k), mdfadd(rs(p), mid + 1, r, k);
pushup(p, k);
}
il void mdfor(int p, int l, int r, int pl, int pr, int k) {
if(pl <= l && r <= pr) {
mdfadd(p, l, r, k);
pushadd(p, l, r, k);
return ;
}
pushdown(p, l, r, k);
int mid = (l + r) >> 1;
if(pl <= mid) mdfor(ls(p), l, mid, pl, pr, k);
if(pr > mid) mdfor(rs(p), mid + 1, r, pl, pr, k);
pushup(p, k);
}
il int query(int p, int l, int r, int pl, int pr) {
if(pl <= l && r <= pr) return t[p].mx;
pushdown1(p, l, r);
int mid = (l + r) >> 1, mx = 0;
if(pl <= mid) mx = max(mx, query(ls(p), l, mid, pl, pr));
if(pr > mid) mx = max(mx, query(rs(p), mid + 1, r, pl, pr));
return mx;
}
}
bool End;
il void Usd() {cerr << (&Beg - &End) / 1024.0 / 1024.0 << "MB " << (double)clock() * 1000.0 / CLOCKS_PER_SEC << "ms\n"; }
int main() {
read(n), read(q);
for(int i = 1; i <= n; i++) read(a[i]);
pw[0] = 1;
for(int i = 1; i <= 21; i++) pw[i] = pw[i - 1] * 2;
SGT::build(1, 1, n);
while(q--) {
int opt, l, r, x;
read(opt), read(l), read(r);
switch(opt) {
case 1: {
read(x);
for(int i = 0; i < MX; i++) if(!((x >> i) & 1)) SGT::mdfand(1, 1, n, l, r, i);
break;
}
case 2: {
read(x);
for(int i = 0; i < MX; i++) if((x >> i) & 1) SGT::mdfor(1, 1, n, l, r, i);
break;
}
case 3: {
write(SGT::query(1, 1, n, l, r));
break;
}
}
}
Usd();
return 0;
}

浙公网安备 33010602011771号