ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

2022“杭电杯”中国大学生算法设计超级联赛(2) 题解

2022-07-26 10:03:46  阅读:116  来源: 互联网

标签:return int 题解 mid MAXN 2022 res 杭电杯 define


A. Static Query on Tree

将集合 \(|A|,|B|,|C|\) 内取出的点记为 \(a,\ b,\ c\),我们可以从题目条件中提取三个信息

① 满足要求的点一定在 a到c 的这条链上

② 满足要求的点一定在 b到c 的这条链上

③ 满足要求的点一定在 c 的子树内

利用树链剖分+线段树,我们可以在树上维护 \(a,\ b,\ c\) 三个标记,表示是否分别满足这三个条件,最后求出同时满足这三个条件的点的数量。

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int MAXN = (int)2e5 + 5;

struct Segment_Tree {
	struct Node {
	    int maxx, sum[4], tag[2];
	}tree[MAXN << 2];
	
	void Init(int l, int r, int p) {
		tree[p].sum[0] = r - l + 1;
		for(int i = 1; i < 4; i++) tree[p].sum[i] = 0;
		tree[p].tag[1] = 1, tree[p].tag[0] = 0;
	}
	
	void Calc(int l, int r, int p, int k) {
		for(int i = 3; i >= 0; i--) {
			if( (i | k) == i ) continue;
			tree[p].sum[i | k] += tree[p].sum[i];
			tree[p].sum[i] = 0;
		}
		tree[p].tag[0] |= k;
	}
	
	void PushUp(int l, int r, int p) {
		for(int i = 0; i < 4; i++) tree[p].sum[i] = tree[p << 1].sum[i] + tree[p << 1 | 1].sum[i];
	}
	
	void PushDown(int l, int r, int p) {
		int mid = l + r >> 1;
		if(tree[p].tag[1]) {
			Init(l, mid, p << 1);
			Init(mid + 1, r, p << 1 | 1);
			tree[p].tag[1] = 0;
		}
		if(tree[p].tag[0]) {
			Calc(l, mid, p << 1, tree[p].tag[0]);
			Calc(mid + 1, r, p << 1 | 1, tree[p].tag[0]);
			tree[p].tag[0] = 0;
		}	
	}
	
	void Build(int l, int r, int p) {
		Init(l, r, p);
		if(l == r) return ;
	    int mid = l + r >> 1;
	    Build(l, mid, p << 1);
	    Build(mid + 1, r, p << 1 | 1);
	    PushUp(l, r, p);
	}
	
	void Modify(int nl, int nr, int l, int r, int p, int k) {
	    if(nl <= l && nr >= r) return void( Calc(l, r, p, k) );
	    PushDown(l, r, p);
	    int mid = l + r >> 1;
	    if(nl <= mid) Modify(nl, nr, l, mid, p << 1, k);
	    if(nr > mid) Modify(nl, nr, mid + 1, r, p << 1 | 1, k);
	    PushUp(l, r, p);
	}
	
	int Query(int nl, int nr, int l, int r, int p) {
		int mid = l + r >> 1, res = 0;
		if(nl <= l && nr >= r) {
			res = tree[p].sum[3];
			Init(l, r, p);
			return res;
		}
		PushDown(l, r, p);
		if(nl <= mid) res += Query(nl, nr, l, mid, p << 1);
		if(nr > mid) res += Query(nl, nr, mid + 1, r, p << 1 | 1);
		PushUp(l, r, p);
		return res;
	}
}Seg;

int fa[MAXN], sze[MAXN], son[MAXN], dep[MAXN];
int id[MAXN], val[MAXN], top[MAXN], cnt;
vector<int> G[MAXN];
int n, q, a[MAXN], b[MAXN], c[MAXN];

void DFS1(int u, int f) {
    fa[u] = f, sze[u] = 1, son[u] = 0, dep[u] = dep[f] + 1;
    int maxsize = -1;
    for(auto v : G[u]) {
        DFS1(v, u);
        if(sze[v] > maxsize) maxsize = sze[v], son[u] = v;
        sze[u] += sze[v];
    }
}

void DFS2(int u, int topu) {
    id[u] = ++cnt, val[cnt] = u, top[u] = topu;
    if(son[u] == 0) return ;
    DFS2(son[u], topu);
    for(auto v : G[u]) if(v != son[u] && v != fa[u]) DFS2(v, v);
}

void Modify(int u, int k) {
    int v = 1;
    while(top[u] != top[v]) {
        if(dep[top[u]] < dep[top[v]]) swap(u, v);
        Seg.Modify(id[top[u]], id[u], 1, n, 1, k);
        u = fa[top[u]];
    }
    if(id[u] > id[v]) swap(u, v);
    Seg.Modify(id[u], id[v], 1, n, 1, k);
}

void Solve() {
    cin >> n >> q; cnt = 0;
    for(int i = 1; i <= n; i++) G[i].clear();
    for(int i = 2; i <= n; i++) { int u; cin >> u; G[u].push_back(i); }
    DFS1(1, 0), DFS2(1, 1), Seg.Build(1, n, 1);
    while(q--) {
        int A, B, C; cin >> A >> B >> C;
    	Seg.Init(1, 1, n);
        for(int i = 1; i <= A; i++) cin >> a[i], Modify(a[i], 1);
        for(int i = 1; i <= B; i++) cin >> b[i], Modify(b[i], 2);
        
		int ans = 0;
        for(int i = 1; i <= C; i++) {
        	cin >> c[i];
        	ans += Seg.Query(id[ c[i] ], id[ c[i] ] + sze[ c[i] ] - 1, 1, n, 1);
        }
        cout << ans << "\n";
    }
}

signed main()
{
    ios::sync_with_stdio(false); cin.tie(0);
    int T; cin >> T;
    while(T--) Solve();
    return 0;
}

B. C++ to Python

签到题,模拟即可

#include<bits/stdc++.h>
using namespace std;

string S;

void Solve() {
	cin >> S;
	for(int i = 0; i < S.length(); i++) {
		bool flag = 0;
		if(S[i] == '(') flag = 1;
		else if(S[i] == ')') flag = 1;
		else if(S[i] == ',') flag = 1;
		else if(S[i] == '-') flag = 1;
		else if(S[i] >= '0' && S[i] <= '9') flag = 1;
		if(flag) cout << (char)S[i];
	}
	cout << "\n";
}

signed main()
{
	int T; cin >> T;
	while(T--) Solve();
	return 0;
} 

C. Copy

考虑修改操作对后续的查询操作的影响:如果 \(x \leq r\) 就没影响,如果 \(x>r\) ,则相当于查询 \(x - (r - l + 1)\)。

正着考虑所有修改操作,发现从分裂区间的角度不好处理。利用正难则反的原则,我们倒着考虑所有修改操作,此时从合并区间的角度处理操作。

又因为输出所有答案的异或值,我们发现相同结果的两个查询可以抵消,一个结果可被利用0或1次,

设 \(dp[i]\) 为 \(a[i]\) 被利用几次,则dp值可以用bitset维护,有:

① 对于查询操作,\(dp[i] = dp[i] \oplus 1\),其中\(\oplus\)表示异或符号;

② 对于修改操作,我们令 \(i>r\) 的所有dp值往左移 \(r-l+1\) 位,并与 \(i \leq r\) 的所有dp值进行异或操作。

#include<bits/stdc++.h>
#define int long long
#define pir make_pair
#define pii pair<int, int>
#define fi first
#define se second
using namespace std;

const int MAXN = 1e5 + 5;

int n, q, a[MAXN], l[MAXN], r[MAXN], op[MAXN];
bitset<MAXN> vis; 

void Solve() {
	scanf("%lld%lld", &n, &q);
	for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
	for(int i = 1; i <= q; i++) {
		scanf("%lld", &op[i]);
		if(op[i] == 1) scanf("%lld%lld", &l[i], &r[i]);
		else scanf("%lld", &l[i]);
	}
	vis = 0;
	for(int i = q; i >= 1; i--) {
		if(op[i] == 1) {
			bitset<MAXN> cur, res1, res2;
			cur = 0, cur.flip(), cur <<= (r[i] + 1);
			res1 = (vis & cur) >> (r[i] - l[i] + 1);
			cur = 0, cur.flip(), cur >>= (MAXN - 1 - r[i]);
			res2 = (vis & cur);
			vis = res1 ^ res2;
		} else vis[ l[i] ].flip();
	}
	int ans = 0;
	for(int i = 1; i <= n; i++) if(vis[i]) ans ^= a[i];
	cout << ans << "\n";
}

signed main()
{
	int TT; scanf("%lld", &TT);
	while(TT--) Solve();
	return 0;
}  

E. Slayers Come

我们将解题过程分为两个步骤:

① 求出每个技能能杀死怪物的区间

② 对于①处理出来的 \(m\) 个区间,我们求出有多少种选择区间方案,满足选出来的区间能覆盖这n个点

用两个线段树处理这两个过程。

对于①,我们先考虑技能往左的情况,将不等式化为 \(a_j - b_{j-1} \geq L_i\) ,此时我们需要找到满足 \(a_j - b_{j-1} < L_i\) 的最大位置,用线段树二分即可解决。对于技能往右的情况同理。

对于②,我们先对所有区间按右端点升序排序,并设 \(dp[i]\) 为覆盖 \([1, i]\) 的方案数,则对于一个新加入的区间,有:

\[dp[r] = \sum_{i=l-1}^{r} dp[i] \\ dp[i] *= 2, \ i \in [1, l-2] \]

发现需要支持区间修改区间查询,线段树维护即可

#include<bits/stdc++.h>
#define int long long
#define pir make_pair
#define pii pair<int, int>
#define fi first
#define se second
using namespace std;

const int INF = 0x3f3f3f3f;
const int MAXN = 1e5 + 5;
const int MOD = 998244353;

int n, m, a[MAXN], b[MAXN], f[MAXN];
pii s[MAXN];
vector<int> vec[MAXN];

struct Seg {
	int sum[MAXN << 2], minl[MAXN << 2], minr[MAXN << 2], add[MAXN << 2], mul[MAXN << 2], n;
	
	void PushUp(int p) {
		sum[p] = (sum[p << 1] + sum[p << 1 | 1]) % MOD;
		minl[p] = min(minl[p << 1], minl[p << 1 | 1]);
		minr[p] = min(minr[p << 1], minr[p << 1 | 1]);
	}
	
	void PushDown(int p, int l, int r) {
		int mid = l + r >> 1;
		mul[p << 1] = mul[p << 1] * mul[p] % MOD;
		mul[p << 1 | 1] = mul[p << 1 | 1] * mul[p] % MOD;
		add[p << 1] = (add[p << 1] * mul[p] % MOD + add[p]) % MOD;
		add[p << 1 | 1] = (add[p << 1 | 1] * mul[p] % MOD + add[p]) % MOD;
		sum[p << 1] = (sum[p << 1] * mul[p] % MOD + add[p] * (mid - l + 1) % MOD) % MOD;
		sum[p << 1 | 1] = (sum[p << 1 | 1] * mul[p] % MOD + add[p] * (r - mid) % MOD) % MOD;
		add[p] = 0, mul[p] = 1;
	}
	
	void Build(int l, int r, int p) {
		mul[p] = 1, add[p] = 0;
		if(l == r) {
			sum[p] = 0, minl[p] = a[l] - b[l - 1], minr[p] = a[l] - b[l + 1];
			return ;
		}
		int mid = l + r >> 1;
		Build(l, mid, p << 1);
		Build(mid + 1, r, p << 1 | 1);
		PushUp(p);
	}
	
	int QueryLeftPos(int nl, int nr, int l, int r, int p, int val) {
		int mid = l + r >> 1, res = -1;
		if(l == r) return minl[p] >= val ? -1 : l;
		if(nl <= l && nr >= r) {
			if(minl[p] >= val) return -1;
			if(minl[p << 1 | 1] < val) return QueryLeftPos(nl, nr, mid + 1, r, p << 1 | 1, val);
			else return QueryLeftPos(nl, nr, l, mid, p << 1, val);
		}
		
		if(nr > mid) res = max(res, QueryLeftPos(nl, nr, mid + 1, r, p << 1 | 1, val) );
		if(res > -1) return res;
		if(nl <= mid) res = max(res, QueryLeftPos(nl, nr, l, mid, p << 1, val) );
		return res;
	}
	
	int QueryRightPos(int nl, int nr, int l, int r, int p, int val) {
		int mid = l + r >> 1, res = INF;
		if(l == r) return minr[p] >= val ? INF : l;
		if(nl <= l && nr >= r) {
			if(minr[p] >= val) return INF;
			if(minr[p << 1] < val) return QueryRightPos(nl, nr, l, mid, p << 1, val);
			else if(minr[p << 1 | 1] < val) return QueryRightPos(nl, nr, mid + 1, r, p << 1 | 1, val);
		}
		
		if(nl <= mid) res = min(res, QueryRightPos(nl, nr, l, mid, p << 1, val) );
		if(res < INF) return res;
		if(nr > mid) res = min(res, QueryRightPos(nl, nr, mid + 1, r, p << 1 | 1, val) );
		return res;
	}
	
	int QuerySum(int nl, int nr, int l, int r, int p) {
		if(nl <= l && nr >= r) return sum[p];
		PushDown(p, l, r);
		int res = 0, mid = l + r >> 1;
		if(nl <= mid) res += QuerySum(nl, nr, l, mid, p << 1);
		if(nr > mid) res += QuerySum(nl, nr, mid + 1, r, p << 1 | 1);
		res %= MOD;
		return res;
	}
	
	void ModifyAdd(int nl, int nr, int l, int r, int p, int val) {
		if(l == r) {
			add[p] = (add[p] + val) % MOD;
			sum[p] = (sum[p] + val * (r - l + 1) % MOD) % MOD;
			return ;
		}
		int mid = l + r >> 1;
		if(nl <= mid) ModifyAdd(nl, nr, l, mid, p << 1, val);
		if(nr > mid) ModifyAdd(nl, nr, mid + 1, r, p << 1 | 1, val);
		PushUp(p);
	}

	void ModifyMul(int nl, int nr, int l, int r, int p, int val) {
		if(nl <= l && nr >= r) {
			mul[p] = mul[p] * val % MOD;
			add[p] = add[p] * val % MOD;
			sum[p] = sum[p] * val % MOD;
			return ;
		}
		int mid = l + r >> 1;
		if(nl <= mid) ModifyMul(nl, nr, l, mid, p << 1, val);
		if(nr > mid) ModifyMul(nl, nr, mid + 1, r, p << 1 | 1, val);
		PushUp(p);
	}
	
	void Init(int x) {
		n = x;
		Build(1, n, 1);
	}
}Left, Right, Sum;

void Solve() {
	scanf("%lld%lld", &n, &m);
	for(int i = 1; i <= n; i++) scanf("%lld%lld", &a[i], &b[i]), f[i] = 0;
	
	b[0] = b[n + 1] = INF;
	Left.Init(n); Right.Init(n); Sum.Init(n + 1);
	for(int i = 1; i <= m; i++) {
		int m, L, R; scanf("%lld%lld%lld", &m, &L, &R);
		
		s[i] = pir(
			Left.QueryLeftPos(1, m, 1, n, 1, L),
			Right.QueryRightPos(m, n, 1, n, 1, R)
		);
		if(s[i].fi <= -1) s[i].fi = m;
		if(s[i].se >= INF) s[i].se = m;
	}
	
	for(int i = 1; i <= m; i++) swap(s[i].fi, s[i].se);
	sort(s + 1, s + 1 + m);
	for(int i = 1; i <= m; i++) swap(s[i].fi, s[i].se);
	
	f[0] = 1;
	Sum.ModifyAdd(1, 1, 1, n + 1, 1, 1);
	for(int i = 1; i <= m; i++) {
		int l = s[i].fi, r = s[i].se;
		f[r] = Sum.QuerySum(l, r + 1, 1, n + 1, 1);
		Sum.ModifyAdd(r + 1, r + 1, 1, n + 1, 1, f[r]);
		if(l - 1 >= 1) Sum.ModifyMul(1, l - 1, 1, n + 1, 1, 2);
	}
	cout << Sum.QuerySum(n + 1, n + 1, 1, n + 1, 1) << "\n";
}

signed main()
{
	int TT; scanf("%lld", &TT);
	while(TT--) Solve();
	return 0;
} 

F. Bowcraft

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
#define pir make_pair
#define pii pair<int, int>
#define fi first
#define se second
using namespace std;
const int MAXN = 1000 + 5;
const int MOD = 1e9 + 7;
const int INF = 1e18;

struct Node {
	int a, b;
	double w;
};

int K, A, B;
double f[MAXN];
vector<Node> vec;

bool cmp(const Node& a, const Node& b) {
	return a.w < b.w;
}

double min(double a, double b) {
	return a > b ? b : a;
}

void Solve() {
	cin >> K >> A >> B;
	vec.clear();
	for(int a = 1; a < A; a++) {
		for(int b = 0; b < B; b++) {
			double w = 1.0 * b * A / (B * a) - 1.0 * b / B;
			vec.push_back({a, b, w});
		}
	}
	sort(vec.begin(), vec.end(), cmp);
	f[0] = 0;
	for(int i = 1; i <= K; i++) {
		double sum1 = 0, sum2 = 0;
		int cnt = 0;
		f[i] = INF;
		for(auto k : vec) {
			int a = k.a, b = k.b, w = k.w;
			sum1 += 1.0 * a / A + 1.0 * b / B - 1.0 * a * b / (A * B);
			sum2 += (1.0 * (A - a) / A);
			cnt++;
			double cur = A * B + sum1 * f[i - 1];
			cur /= (1.0 * cnt - sum2);
			f[i] = min(f[i], cur);
		}
	}
	printf("%.3lf\n", f[K]);
}

signed main()
{
	//ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int T; cin >> T;
	while(T--) Solve();
	return 0;
}

G. Snatch Groceries

根据贪心思想,首先按 \(earliest\) 为第一关键字,\(latest\) 为第二关键字升序排序,

枚举下一个区间,判断当前区间是否与上一个区间相交即可。

#include<bits/stdc++.h>
#define int long long
#define pir make_pair
#define pii pair<int, int>
#define fi first
#define se second
using namespace std;

const int INF = 0x3f3f3f3f;
const int MAXN = 1e5 + 5;

int n;
pii a[MAXN];

void Solve() {
	scanf("%lld", &n);
	for(int i = 1; i <= n; i++) {
		scanf("%lld%lld", &a[i].fi, &a[i].se);
	}
	sort(a + 1, a + 1 + n);
	int ans = 0, flag = 1;
	for(int i = 1; i < n; i++) {
		if(a[i].se < a[i + 1].fi) ans++;
		else { flag = 0; break; }
	}
	if(flag) ans++;
	cout << ans << "\n";
}

signed main()
{
	int TT; scanf("%lld", &TT);
	while(TT--) Solve();
	return 0;
} 

H. Keyboard Warrior

K. DOS Card

设 \(i,\ j,\ k,\ l\) 为区间内选出来的四个数的下标,令其组成两对,有两种情况:

① \(a_i^2+a_j^2-a_k^2-a_l^2\) ② \(a_i^2-a_j^2+a_k^2-a_l^2\)

为了简化后续操作,我们将其称为 ①\(++--\) ②\(+-+-\) (+-分别代表这四个数对答案贡献的正负)

逐步拆解成两个部分,有

\[\left\{ \begin{array}{**lr**} ++-- \left\{ \begin{array}{**lr**} +,+-- \\ ++,-- \\ ++-,- \\ \end{array} \right. \\ +-+- \left\{ \begin{array}{**lr**} +,-+- \\ +-,+- \\ +-+,- \\ \end{array} \right. \end{array} \right. \]

发现对于\(-,+,--,++\)的情况,我们用\(Max1, Max2,Min1, Min2\)维护

对于\(+-\)的情况,我们用\(aPairMax\)维护

对于\(++-,+-+\)的情况,我们用\(ValAddMax\)维护,因为这两种情况下,剩下的\(-\)只能放置于一端,所以只需要用一个变量维护

对于\(+--,-+-\)的情况,我们用\(ValMinusMax\)维护,因为这两种情况下,剩下的\(+\)只能放置于一端,所以只需要用一个变量维护

对于这\(ValAddMax,\ ValMinusMax\)的维护,我们将上述四种情况继续拆解即可

最后再用\(twoPairMax\)维护\(++--,+-+-\)的最大值

线段树的\(PushUp\)操作即是维护上述操作的过程

#include<bits/stdc++.h>
#define int long long
#define pir make_pair
#define pii pair<int, int>
#define fi first
#define se second
using namespace std;

const int MAXN = 4e5 + 5;
const int INF = 1e18;

struct Node {
	int Max1, Max2;
	int Min1, Min2;
	int aPairMax;
	int twoPairMax;
	int ValAddMax;
	int ValMinusMax;
	int len;
	
	void Init() {
		Max1 = Max2 = -INF;
		Min1 = Min2 = INF;
		aPairMax = -INF;
		twoPairMax = -INF;
		ValAddMax = -INF;
		ValMinusMax = -INF;	
	}
}tree[MAXN << 2];

int n, m, a[MAXN];

Node PushUp(Node ls, Node rs) {
	Node res;
	res.len = ls.len + rs.len;
	
	res.Max1 = max(ls.Max1, rs.Max1);
	
	res.Max2 = max( min(ls.Max1, rs.Max1), max(ls.Max2, rs.Max2) );
	
	res.Min1 = min(ls.Min1, rs.Min1);
	
	res.Min2 = min( max(ls.Min1, rs.Min1), min(ls.Min2, rs.Min2) );
	
	res.aPairMax = max({
		ls.aPairMax, 
		rs.aPairMax, 
		ls.Max1 - rs.Min1
	});
	
	res.twoPairMax = max({
		ls.twoPairMax, 
		rs.twoPairMax,
		ls.aPairMax + rs.aPairMax,
		ls.Max1 + ls.Max2 - rs.Min1 - rs.Min2,
		ls.ValAddMax - rs.Min1,
		ls.Max1 + rs.ValMinusMax
	});
	
	res.ValAddMax = max({
		ls.ValAddMax,
		rs.ValAddMax,
		ls.aPairMax + rs.Max1,
		rs.aPairMax + ls.Max1
	});
	if(ls.len >= 2) res.ValAddMax = max(res.ValAddMax, ls.Max1 + ls.Max2 - rs.Min1);
	if(rs.len >= 2) res.ValAddMax = max(res.ValAddMax, ls.Max1 + rs.Max1 - rs.Min1);
	
	res.ValMinusMax = max({
		ls.ValMinusMax,
		rs.ValMinusMax,
		ls.aPairMax - rs.Min1,
		rs.aPairMax - ls.Min1
	});
	if(ls.len >= 2) res.ValMinusMax = max(res.ValMinusMax, ls.Max1 - ls.Min1 - rs.Min1);
	if(rs.len >= 2) res.ValMinusMax = max(res.ValMinusMax, ls.Max1 - rs.Min1 - rs.Min2);
	return res;
}

void Build(int l, int r, int p) {
	tree[p].Init();
	if(l == r) {
		tree[p].Max1 = a[l] * a[l];
		tree[p].Min1 = a[l] * a[l];
		tree[p].len = 1;
		return ;
	}
	int mid = l + r >> 1;
	Build(l, mid, p << 1);
	Build(mid + 1, r, p << 1 | 1);
	tree[p] = PushUp(tree[p << 1], tree[p << 1 | 1]);
}

Node Query(int nl, int nr, int l, int r, int p) {
	if(nl <= l && nr >= r) return tree[p];
	int mid = l + r >> 1;
	if(nr <= mid) return Query(nl, nr, l, mid, p << 1);
	else if(nl > mid) return Query(nl, nr, mid + 1, r, p << 1 | 1);
	else return PushUp( Query(nl, nr, l, mid, p << 1), Query(nl, nr, mid + 1, r, p << 1 | 1) );
}

void Solve() {
	scanf("%lld%lld", &n, &m);
	for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
	Build(1, n, 1);
	
	while(0) {
		int l, r; cin >> l >> r;
		Node cur = Query(l, r, 1, n, 1);
		cout << cur.Max1 << " Max1\n";
		cout << cur.Max2 << " Max2\n";
		cout << cur.Min1 << " Min1\n";
		cout << cur.Min2 << " Min2\n";
		cout << cur.aPairMax << " aPairMax\n";
		cout << cur.twoPairMax << " twoPairMax\n";
		cout << cur.ValAddMax << " ValAddMax\n";
		cout << cur.ValMinusMax << " ValMinusMax\n";
	}
	
	while(m--) {
		int l, r; scanf("%lld%lld", &l, &r);
		printf("%lld\n", Query(l, r, 1, n, 1).twoPairMax );
	}
}

signed main()
{
	int TT; scanf("%lld", &TT);
	while(TT--) Solve();
	return 0;
}  

L. Luxury cruise ship

发现7,31,365三个数互质,可以先预处理出7 * 31 * 365的背包,大于7 * 31 * 365的部分直接用365填充即可。

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int INF = 0x3f3f3f3f;

int f[90005];

signed main()
{
	int n = 80000, lcm = 79205;
	memset(f, 0x3f, sizeof f);
	f[0] = 0;
	for(int i = 1; i <= n; i++) {
		if(i >= 7) f[i] = min(f[i], f[i - 7] + 1);
		if(i >= 31) f[i] = min(f[i], f[i - 31] + 1);
		if(i >= 365) f[i] = min(f[i], f[i - 365] + 1);
	}
	
	int T; cin >> T;
	while(T--) {
		cin >> n;
		int ans = 0;
		ans += (n / lcm) * (lcm / 365);
		n %= lcm;
		ans += f[n];
		if(f[n] >= INF) ans = -1;
		cout << ans << "\n";
	}
	return 0;
} 

标签:return,int,题解,mid,MAXN,2022,res,杭电杯,define
来源: https://www.cnblogs.com/Orzjh/p/16519775.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有