正睿 25 年省选联考 Day 18

正睿 25 年省选联考 Day 18

\(\text{Link}\)

得分

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;
}
posted @ 2025-04-25 10:06  UKE_Automation  阅读(21)  评论(0)    收藏  举报