2026 海亮夏令营题单与知识点总结

总览

日期作业题数比赛题数去重后题数主要算法
7 月 7 日488模拟、BFS、括号贡献、生成树
7 月 8 日15015基环树 DP、单调队列、线段树
7 月 9 日344排序、分组背包、单调队列
7 月 10 日606离散化、权值树、可持久化线段树
7 月 11 日444贪心、0/1 背包、高维差分
7 月 13 日444位运算、字典序 BFS、树上贪心、容斥
7 月 14 日10010质数、分解、gcd、同余与逆元
7 月 15 日444二分、分类讨论、字符串 DP、搜索剪枝
7 月 16 日707组合数学、欧拉函数、区间筛、反素数
7 月 17 日444环上模拟、反射展开、树形 DP、树上覆盖
7 月 19 日444构造、贪心拆分、债务净额、路径背包
7 月 20 日606次短路、最短路计数、0-1 BFS、负环
7 月 21 日444字典序、多边形判定、数据结构优化 DP
7 月 22 日707直径、树上 DP、Tarjan LCA、树上差分
7 月 23 日588最短路、最大生成树、逆序对、欧拉函数

7 月 7 日

题单

来源题号 / 题名(全部可点)
比赛 + 订正作业A 地雷 · 2863 地雷(订正)
比赛 + 订正作业B 立方体 · 2864 立方体(订正)
比赛 + 订正作业C 括号 · 2865 括号(订正)
比赛D 卡牌
比赛E 区间
比赛 + 订正作业F 生成树 · 2868 生成树(订正)
比赛G 排列
比赛H 字符串

知识点

Code

A 地雷
	for(int i = 1;i <= k;i++){
		int x, y;cin >> x >> y;
		b[x][y] = -1;
		d[x + 1][y]++;
		d[x][y + 1]++;
		d[x - 1][y]++;
		d[x][y - 1]++;
		d[x + 1][y + 1]++;
		d[x - 1][y + 1]++;
		d[x + 1][y - 1]++;
		d[x - 1][y - 1]++;
	}
B 立方体
void bfs(int sx, int sy, int sz, int cnt) {
	queue<node> q;
    q.push({sx, sy, sz, cnt});
    v[sx][sy][sz] = 1;
    while (q.size()) {
        node u = q.front();
        q.pop();
        int x = u.x, y = u.y, z = u.z, cnt = u.cnt;
        v[x][y][z] = 0;
        if (x > n or y > n or z > n or x < 1 or y < 1 or z < 1)
            continue;
        if (u.cnt > ds[x][y][z])
            continue;
        ds[x][y][z] = u.cnt;
        if (!d[x + 1][y][z] and !v[x + 1][y][z]) {
            q.push({ x + 1, y, z, cnt + 1 });
            v[x + 1][y][z] = 1;
        }
        if (!d[x][y + 1][z] and !v[x][y + 1][z]) {
            q.push({ x, y + 1, z, cnt + 1 });
            v[x][y + 1][z] = 1;
        }
        if (!d[x - 1][y][z] and !v[x - 1][y][z]) {
            q.push({ x - 1, y, z, cnt + 1 });
            v[x - 1][y][z] = 1;
        }
        if (!d[x][y - 1][z] and !v[x][y - 1][z]) {
            q.push({ x, y - 1, z, cnt + 1 });
            v[x][y - 1][z] = 1;
        }
        if (!d[x][y][z + 1] and !v[x][y][z + 1]) {
            q.push({ x, y, z + 1, cnt + 1 });
            v[x][y][z + 1] = 1;
        }
        if (!d[x][y][z - 1] and !v[x][y][z - 1]) {
            q.push({ x, y, z - 1, cnt + 1 });
            v[x][y][z - 1] = 1;
        }
    }
C 括号
void solve(string ss){
	stack<int> s;int cnt = 0;
	for(int i = 0;i < ss.size();i++){
		if(ss[i] == '('){
			cnt++;
		}
		if(ss[i] == ')'){
			cnt--;
			if(ss[i - 1] == '('){
				B[cnt]++;
			}
		}
	}int x = 0;
	for(int i = 0;i <= 5000000;i++){
		B[i] += x;
		x = B[i] / 2;
		B[i] %= 2;
//		cout << B[i];
	}
//	cout << endl;
}
F 生成树
	while(T--){
		scanf("%lld%lld", &n, &m);
		int x = 1.5 + sqrt(2.25 - 2 * (n - m));
//		printf("%lld\n", x);
		int ans = (((x*x)+5)*x/6 + (n-x-1)*(2*m-n+x+2)/2)%MOD;
		printf("%lld\n", ans);
	}

20260707周赛:复盘

题目顺序:T1 = A 地雷;T2 = B 立方体;T3 = C 括号;T4 = D 卡牌;T5 = E 区间;T6 = F 生成树;T7 = G 排列;T8 = H 字符串

项目 T1 T2 T3 T4 T5 T6 T7 T8
涉及算法标签 模拟 搜索 模拟? 数学? - - 数学推导 -
得分 100 32.89 26 - - - - -
备注(拉了)
错误原因 - □ 算法盲区 □ 代码实现写挂 □ 时间不够 □ 时间不够 □ 时间不够 □ 时间不够 □ 时间不够
正确解法核心 同上 同上 同上 - - - 同上 -
以前做过的同类型题 好像无所谓 貌似无 [Junior] 括号匹配 - - - - -
今天最大的教训纯傻福来的
需要补的知识漏洞三维的BFS???

7 月 8 日

题单(去重后 15 题)

来源题号 / 题名(全部可点)
作业P3554 [POI 2013] LUK-Triumphal arch
作业P1613 跑路
作业P10933 创世纪
作业255 [ZJOI2008] 骑士
作业2929 城市环路
作业DPM Candies
作业P1886 滑动窗口 /【模板】单调队列
作业2887 琪露诺
作业P6040 「ACOI2020」课后期末考试滑溜滑溜补习班
作业P2569 [SCOI2010] 股票交易
作业DPQ Flowers
作业P3372 【模板】线段树 1
作业P3373 【模板】线段树 2
作业P2846 [USACO08NOV] Light Switching G
作业2931 [USACO08FEB] Hotel G

知识点

Code

P10933 创世纪
void dfs(int u, int root, bool flag) {
    dfn[u] = 1;
    dp[u][0] = 0;
    int mi = INT_MAX;
    for (auto v : adj[u]) {
        if (v == root)
            continue;
        dfs(v, root, flag);
        dp[u][0] += max(dp[v][1], dp[v][0]);
        mi = min(mi, max(dp[v][0], dp[v][1]) - dp[v][0]);
    }
	dp[u][1] = 1 + dp[u][0] - mi;
	if (flag && u == a[root]){
		dp[u][1] += mi;
	}
}
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        adj[a[i]].push_back(i);
    }
    int sum = 0;
    for (int x = 1; x <= n; x++) {
        if (!dfn[x]) {
            while (!vis[x]) {   //环 
                vis[x] = 1;
                x = a[x];
            }
            dfs(x, x, 0);      
//			cout << x; 
            int ans = max(dp[x][0], dp[x][1]);
            dfs(x, x, 1);
            sum += max(dp[x][0], ans);
        }
    }
    cout << sum;

7 月 9 日

题单(去重后 4 题)

来源题号 / 题名(全部可点)
比赛 + 订正作业A 数对(Pair) · A. 数对(Pair)(订正)
比赛 + 订正作业B 魔法升级(Magic) · 2911 魔法升级(Magic)(订正)
比赛 + 订正作业C 香蕉树(Banana) · 2912 香蕉树(Banana)(订正)
比赛D 天赋点(Talent)

知识点

Code

A 数对(Pair)
	for(int i = 1;i <= n * 2;i++){
		int x, y;cin >> x >> y;
		ans += max(x, y);sum[i] = x + y;
	}
	sort(sum + 1, sum + 1 + n * 2);
	for(int i = 1;i <= n;i++){
		ans -= sum[i]; 
	} 
	cout << ans;
B 魔法升级(Magic)
	for(int ii = 1;ii <= tot;ii++){
		bool i = ii % 2;
		for(int j = 0;j <= m;j++){
			dp[i][j][0] = dp[i][j][1] = 0;
		}
		for(int j = 0;j <= m;j++){
			ans[i][j][0] = ans[i][j][1] = zero;
			if(j >= c[num[ii]]){
				if(num[ii] != num[ii - 1]){
					int kk = dp[!i][j - c[num[ii]]][0] < dp[!i][j - c[num[ii]]][1] ? 1 : 0;
					dp[i][j][1] = dp[!i][j - c[num[ii]]][kk] + w[ii];
					ans[i][j][1] = ans[!i][j - c[num[ii]]][kk];
					add(i, j, 1, ii);
				}else{
					dp[i][j][1] = dp[!i][j - c[num[ii]]][1] + w[ii];
					ans[i][j][1] = ans[!i][j - c[num[ii]]][1];
					add(i, j, 1, ii);
				}
			}
			int kk = dp[!i][j][0] < dp[!i][j][1] ? 1 : 0;
			dp[i][j][0] = dp[!i][j][kk];
			ans[i][j][0] = ans[!i][j][kk];
C 香蕉树(Banana)
	for(int j = 1;j <= k;j++){
		for(int i = 2;i <= n;i++){
			while(l <= r and dp[q[j - 1][r]][j - 1] <= dp[i - 1][j - 1]){
				r--;
			}q[j - 1][++r] = i - 1;
			while(l <= r and abs(d[i] - d[q[j - 1][l]]) > m){
				l++;
			}
			
//			cout << q[j-1][l] << ' ';
			dp[i][j] = max(dp[q[j - 1][l]][j - 1] + a[i], dp[i][j]);
//			cout << i << ' ' << j << ' ' << dp[i][j] << endl;
			ans = max(ans, dp[i][j]);
		}
	}

普转提20260709模拟赛:复盘

题目顺序:T1 = A 数对(Pair);T2 = B 魔法升级(Magic);T3 = C 香蕉树(Banana);T4 = D 天赋点(Talent)

项目 T1 T2 T3 T4
涉及算法标签 数学推导 分组背包 单调队列优化DP 概率DP
得分 100 100 0 -
错误原因 - - □ 代码实现写挂 □ 时间不够
正确解法核心 同上 同上 同上 -
以前做过的同类型题 分组背包-旅行者的背包 分组背包-旅行者的背包
今天最大的教训提升代码实现&debug能力
需要补的知识漏洞(概率DP?)

7 月 10 日

题单(去重后 6 题)

来源题号 / 题名(全部可点)
作业P1496 火烧赤壁
作业P1908 逆序对
作业luogu#P3369 【模板】普通平衡树
作业P3919 【模板】可持久化线段树 1(可持久化数组)
作业2944 【模板】可持久化线段树 2
作业P3168 [CQOI2015] 任务查询系统

知识点

Code

2944 【模板】可持久化线段树 2
void mdy(int &p, int l, int r, int d) {
	t[++id] = t[p]; p = id;
	t[p].d++;
//	pushup(pp);
    if (l == r) {
        return;
    }
    int mid = (l + r) >> 1;
    if (d <= mid)
        mdy(t[p].l, l, mid, d);
    else
        mdy(t[p].r, mid + 1, r, d);
}
int qry(int p, int q, int l, int r, int k) {
    if (l == r)
        return l;
    int mid = (l + r) >> 1;
    int lcnt = t[t[p].l].d - t[t[q].l].d;
    if (k <= lcnt)
        return qry(t[p].l, t[q].l, l, mid, k);
    else
        return qry(t[p].r, t[q].r, mid + 1, r, k - lcnt);
}
luogu#P3369 【模板】普通平衡树
void mdy(int &p, int l, int r, int d, int v) {
	if (!p) p = ++id;
    if (l == r) {
        t[p].d += v;
        return;
    }
    int mid = (l + r) >> 1;
    if (d <= mid)
        mdy(t[p].l, l, mid, d, v);
    else
        mdy(t[p].r, mid + 1, r, d, v);
    pushup(p);
}
int tk(int p, int l,int r,int v){
	if(l == r) return l;
	int mid = (l + r) >> 1;
	if(v <= t[t[p].l].d) return tk(t[p].l, l, mid, v);
	else return tk(t[p].r, mid + 1, r, v - t[t[p].l].d);
}

7 月 11 日

题单(去重后 4 题)

来源题号 / 题名(全部可点)
比赛 + 订正作业A 慢跑 · 2983 慢跑(订正)
比赛 + 订正作业B 对战 · 2984 对战(订正)
比赛 + 订正作业C 回文串 · 2985 回文串(订正)
比赛 + 订正作业D 读档 · 2986 读档(订正)

知识点

Code

A 慢跑
	int cnt = 1, j = n;
	for(int i = j - 1;i >= 1;i--){
		while(b[i] > b[j]) i--;
		if(b[i] <= b[j] and i > 0){
			cnt++;j = i;
//			cout << i << endl;
		} 
	}
B 对战
    for (int i = 1; i <= n; i++) { cin >> a[i]; tot += a[i]; }
    dp[0] = 1;
    for (int i = 1; i <= n; i++)
        for (int j = tot; j >= a[i]; j--) 
            dp[j] |= dp[j - a[i]];
    for (int i = tot / 2; i >= 0; i--)
        if (dp[i]) { cout << tot - 2 * i << '\n'; return 0; }
C 回文串
		int o = 0, e = 0, cnt = 0;
		for(int i = 1;i <= n;i++){
			cin >> a[i];
			if(a[i] % 2 == 0) e += a[i];
			else{
				cnt++;
				o += a[i] - 1;
			}
		}
		if(cnt == 0) cout << e <<'\n';
		else cout << (int)((o + e) / cnt / 2) * 2 + 1 << '\n';
	}
D 读档
	for(int i = n;i >= 1;i--){
		st[i] = tot;tot *= s[i];
	}
	for(int i = 0;i < tot;i++) cin >> b[i];
	for(int d = 1;d <= n;d++){
		for(int i = tot - 1;i >= 0;i--){
			if(i / st[d] % s[d]) b[i] -= b[i - st[d]];
		}
	}

普转提20260711模拟赛:复盘

题目顺序:T1 = A 慢跑;T2 = B 对战;T3 = C 回文串;T4 = D 读档

项目 T1 T2 T3 T4
涉及算法标签 模拟? DP 模拟 高维差分(前缀和)
得分 100 20 100 10
错误原因 - □ 数组越界:j-a[i]>0忘判了 - □ 时间不够
正确解法核心 同上 同上 同上 同上
以前做过的同类型题 无所谓,,,。。。 (类似)01 背包 二维差分数组的操作(PLUS 版)
今天最大的教训检查数组是否越界!
需要补的知识漏洞高维差分?

7 月 13 日

题单(去重后 4 题)

来源题号 / 题名(全部可点)
比赛 + 订正作业A 数位跃迁 · 2988 数位跃迁(订正)
比赛 + 订正作业B 秘符石板 · 2989 秘符石板(订正)
比赛 + 订正作业C 果树引枝 · 2990 果树引枝(订正)
比赛 + 订正作业D 小樱的库洛牌 · 2991 小樱的库洛牌(订正)

知识点

Code

A 数位跃迁
	while(T--){
		int n, s, t;
		cin >> n >> s >> t;
		if(s == t) cout << 0 << '\n';
		else if((s | t) == (1 << n) - 1) cout << (s ^ t) << '\n';
		else cout << (s ^ ((1 << n) - 1)) + (t ^ ((1 << n) - 1)) << '\n';
	}
B 秘符石板
	for(int k = 1;k <= n + m - 2;k++){
		char mn = 'z' + 1;
		

		for(auto x : q){
			int i = x.fi, j = x.se;
			if(i < n) mn = min(mn, a[i + 1][j]);
			if(j < m) mn = min(mn, a[i][j + 1]);
		}
		
		nq.clear();
		
		for(auto x : q){
			int i = x.fi, j = x.se;
			
			if(i < n and a[i + 1][j] == mn and !vis[i + 1][j]){
				vis[i + 1][j] = 1;
				nq.push_back({i + 1, j});
			}
			
			if(j < m and a[i][j + 1] == mn and !vis[i][j + 1]){
				vis[i][j + 1] = 1;
				nq.push_back({i, j + 1});
			}
		}
		
		cout << mn;
		q = nq;
	}
C 果树引枝
void dfs(int u, int fa,int k){
	if(adj[u].size() == 0){
		dp[u] = k + 1;
		return ;
	}
	for(int v : adj[u]){
		if(v == fa) continue;
		dfs(v, u, k);
		dp[u] = max(dp[u], dp[v] - 1);
		if(dp[v] < 2) flag = 0;
	}
//	cout << u << ' ' << dp[u]<<'\n';
}
bool check(int k){
	flag = 1;
	memset(dp, 0, sizeof dp);
	dfs(1, 0, k);
	if(dp[1] > 0 and flag) return 1;
	else return 0;
}
D 小樱的库洛牌
	int ans = 0;

	for(int i = 0;i <= c;i++){
		int tmp = C(c, i) * fac[k - i] % MOD;

		if(i & 1){
			ans = (ans - tmp + MOD) % MOD;
		}else{
			ans = (ans + tmp) % MOD;
		}
	}

普转提20260713模拟赛:复盘

题目顺序:T1 = A 数位跃迁;T2 = B 秘符石板;T3 = C 果树引枝;T4 = D 小樱的库洛牌

项目 T1 T2 T3 T4
涉及算法标签 推导(结论题) 类似BFS搜索 树上DP 容斥+阶乘逆元(类似错排的一般公式)
得分 100 70 80 10
错误原因 - □ 审题看漏条件 □ 手贱开longlong被卡常(???) □ 时间不够
正确解法核心 同上 同上 同上 同上
以前做过的同类型题 无(吧) 犯罪团伙(大数据版) ???算法类似吧 [POI 2013] LUK-Triumphal Arch
今天最大的教训不要瞎开longlong??
需要补的知识漏洞错排

7 月 14 日

题单(去重后 10 题)

来源题号 / 题名(全部可点)
作业HLP804 倒水
作业HLP821 越狱
作业H1003 判素数
作业HLP812 回文质数
作业B2084 质因数分解
作业3019 Prime Distance
作业HLP1393 Hankson的趣味题
作业HLP372 【NOIP2012提高组】同余方程
作业HLP1429 青蛙的约会
作业HLP375 求逆元

知识点

Code

HLP372 同余方程
void exgcd(int a, int b, int &x, int &y) {
    if (b == 0) {
        x = 1;
        y = 0;
        return;
    }
    exgcd(b, a % b, y, x);
    y -= a / b * x;
}

signed main() {
    int a, b, x, y;
    cin >> a >> b;
    exgcd(a, b, x, y);
    x = (x % b + b) % b;
    cout << x << endl;

7 月 15 日

题单(去重后 4 题)

来源题号 / 题名(全部可点)
比赛 + 订正作业A 砍伐树木 · 2987 砍伐树木(订正)
比赛 + 订正作业B 恶作剧1 · 3020 恶作剧1(订正)
比赛 + 订正作业C 恶作剧2 · 3021 恶作剧2(订正)
比赛 + 订正作业D 卡牌游戏 · 3022 卡牌游戏(订正)

知识点

Code

A 砍伐树木
bool check(int k){
	int tot = 0;
	for(int i = 1;i <= n;i++){
		if(a[i] - k >= 0) tot += a[i] - k;
		if(tot >= m) return 1;
	}
	return 0;
}
B 恶作剧1
		int k = (yy - y) * (xx - x);
		
		f = min(f, w - f);
		
		int b = 0;
		if(x < f){
			b = (min(xx, f) - x) * (yy - y);
		}
		
		k += b;
		
		cout << w * h - k * (c + 1) << '\n';
	}
C 恶作剧2
	memset(dp,0x3f,sizeof(dp));
	dp[0][0]=-1;
	
	for(int i=0;i<len;i++){
		for(int j=0;j<=n;j++){
			for(int v=1;v<=i+1;v++){
				int l=i-v+1;
				if(sum[l][i]>j) continue;
				if(dp[l][j-sum[l][i]]>1000) continue;
				
				dp[i+1][j]=min(dp[i+1][j],
					dp[l][j-sum[l][i]]+1);
			}
		}
	}
D 卡牌游戏
void dfs(int id,long long sum[]){
	if(find_ans==1) return;
	if(id==1){
		bool flag=1;
		for(int i=1;i<=n;i++){
			if(sum[i]!=score[i]){
				flag=0;
				break;
			}
		}
		if(flag==1){
			find_ans=1;
		}
		return;
	}
	//branch 1
	for(int i=1;i<=n;i++){
//		if(i>1&&sum[i]==sum[i-1]) continue;
		long long nxt_sum=sum[i]*id;
		if(nxt_sum>score[i]) continue;
		if(score[i]%nxt_sum!=0) continue;
		sum[i]=nxt_sum;
		dfs(id-1,sum);
		sum[i]/=id;
		if(find_ans==1) return;
	}
	//branch 2
	dfs(id-1,sum);
}

普转提260715模拟赛:复盘

题目顺序:T1 = A 砍伐树木;T2 = B 恶作剧1;T3 = C 恶作剧2;T4 = D 卡牌游戏

项目 T1 T2 T3 T4
涉及算法标签 二分答案 数学? DP DFS剪枝
得分 0 40 100 -
错误原因 □ 手滑删东西 -> CE!!!! □ 代码实现写挂 - □ 时间不够
正确解法核心 同上 同上 同上 同上
以前做过的同类型题 二分查找-整数序列 无。。。 没找见,,?? -
今天最大的教训交之前/后检查
需要补的知识漏洞没啥

7 月 16 日

题单(去重后 7 题)

来源题号 / 题名(全部可点)
作业P1305C Kuroni and Impossible Calculation
作业P48 【UR #3】核聚变反应强度
作业P2822 [NOIP 2016 提高组] 组合数问题
作业HLP383 【bzoj2705】[SDOI2012]Longge的问题
作业BZOJ1607 轻拍牛头
作业3019 Prime Distance
作业BZOJ1053 [HAOI2007] 反素数

知识点

Code

3019 Prime Distance
		for(int j = 1;j <= m;j++){
			int st = max(2ll, (l + prime[j] - 1) / prime[j]);

			for(int i = st;i <= r / prime[j];i++){
				p[prime[j] * i - l] = 1;
			}
		}

		int cnt = 0;
		for(int i = l;i <= r;i++){
			if(!p[i - l]){
				a[++cnt] = i;
			}
		}

7 月 17 日

题单(去重后 4 题)

来源题号 / 题名(全部可点)
比赛 + 订正作业A 跑步 · 3040 跑步(订正)
比赛 + 订正作业B 反射 · 3041 反射(订正)
比赛 + 订正作业C 树 · 3042 树(订正)
比赛 + 订正作业D 店铺 · 3043 店铺(订正)

知识点

Code

A 跑步
	for(int i = 1;i <= m;i++){
		cin >> a >> b;
		cnt += a / n;
		a %= n;
		if((a + x >= y and y > x) or ((a + x) % n >= y and (a + x) % n < x)) cnt++;
		x += a;x %= n;
		cnt += b / n;
		b %= n;
		if((b + y >= x and x > y) or ((b + y) % n >= x and (b + y) % n < y)) cnt++;
		y += b;y %= n;
	}
B 反射
    int n, m;
    cin >> n >> m;
    
    int g = __gcd(n, m);
    int ans = (n + m) / g - 2;
    
    cout << ans;
C 树
void dfs2(int u, int fa){
	int m1 = 0, m2 = 0, v1 = 0;
	for(int v : adj[u]){
		if(v == fa) continue;
		int k = md[v] + 1;
		if(k > m1){
			m2 = m1;
			m1 = k;
			v1 = v;
		}else if(k > m2){
			m2 = k;
		}
	}

	for(int v : adj[u]){
		if(v == fa) continue;
		int k = (v == v1 ? m2 : m1);
		father[v] = max(father[u], k) + 1;
		dfs2(v, u);
	}
}
D 店铺
bool check(int x){
    for(int i = (int)node.size() - 1;i >= 0;i--){
        int u = node[i];
        int sum = 0, best = INF;

        for(auto [v, w] : g[u]){
            sum += cnt[v];
            sum = min(sum, m + 1);

            if(len[v] + w <= x){
                best = min(best, len[v] + w);
            }
        }

        if(g[u].empty()){
           
            cnt[u] = 1;
            len[u] = 0;
        }else if(best != INF){
          
            cnt[u] = sum;
            len[u] = best;
        }else{
   
            cnt[u] = min(m + 1, sum + 1);
            len[u] = 0;
        }
    }

    int sum = 0;

    for(int u : root){
        sum += cnt[u];
        if(sum > m) return 0;
    }

    return 1;
}

普转提20260717模拟赛:复盘

题目顺序:T1 = A 跑步;T2 = B 反射;T3 = C 树;T4 = D 店铺

项目 T1 T2 T3 T4
涉及算法标签 模拟 搜索/数学推导 树的直径 DP
得分 100 100 40 10
错误原因 - - □ 代码实现写挂 □ 时间不够
正确解法核心 同上 同上 同上 同上
以前做过的同类型题 无所谓, CF982E E. Billiard 【模板】树的直径
今天最大的教训maybe算法熟练度不高?
需要补的知识漏洞树的直径?

7 月 19 日

题单(去重后 4 题)

来源题号 / 题名(全部可点)
比赛 + 订正作业A 语言 · 3045 语言(订正)
比赛 + 订正作业B 数字划分 · 3046 数字划分(订正)
比赛 + 订正作业C 债权 · 3047 债权(订正)
比赛 + 订正作业D 礼物 · 3048 礼物(订正)

知识点

Code

A 语言
	int n, m;cin >> n >> m;
	if(m < 2) cout << 1;
	else cout << 0;
	for(int i = 2;i <= n;i++){
		if(i > m) cout << 0;
		else cout << 1;
	}
B 数字划分
	for(int i = 1;i <= n;i++){
		int t = 1111111, j = i, tot = 7, cnt = 0;
		while(t){
			while(t * m <= j){
				j -= t * m;
				cnt += tot;
			}
			t /= 10;tot--;
		}
		if(j > 0) cout << -1 << ' ';
		else cout << cnt << ' ';
	}
C 债权
    for(int i = 1;i <= m;i++){
        int x, y, z;
        cin >> x >> y >> z;
        a[x] += z;
        a[y] -= z;
    }

    int ans = 0;
    for(int i = 1;i <= n;i++){
        if(a[i] > 0) ans += a[i];
    }

    cout << ans / 10 << '.' << ans % 10;
D 礼物
void dfs(int u, int fa){
	for(int j = 0;j <= lmt;j++){
		dp[u][j] = dp[fa][j];
		if(j - w[u] >= 0){
			dp[u][j] = max(dp[u][j], dp[fa][j - w[u]] + v[u]);
		}
	}
	for(int j = 1;j <= lmt;j++){
		dp[u][j] = max(dp[u][j], dp[u][j - 1]);
	}
	if(u * 2 <= n && u * 2 <= 127) dfs(u * 2, u);
	if(u * 2 + 1 <= n && u * 2 + 1 <= 127) dfs(u * 2 + 1, u);
}

void solve(int now, int sumw, int sumv){
	if(now == cnt + 1){
		maxx = max(maxx, sumv + dp[ed][x - sumw]);
		return;
	}
	if(sumw + w[a[now]] <= x){
		solve(now + 1, sumw + w[a[now]], sumv + v[a[now]]);
	}
	solve(now + 1, sumw, sumv);
}

普转提260719模拟赛:复盘

题目顺序:T1 = A 语言;T2 = B 数字划分;T3 = C 债权;T4 = D 礼物

项目 T1 T2 T3 T4
涉及算法标签 模拟 模拟? 稍微推导 DP+DFS(剪枝)
得分 100 100 100 30
错误原因 - - - □ 边界 □ 时间不够
正确解法核心 同上 同上 同上 同上
以前做过的同类型题 「第一届太原五中算法与程序挑战赛入门组」语言(同一道!) 无吧 无? ???
今天最大的教训数组开错大小-30pts
需要补的知识漏洞居然还能DP预处理再DFS暴搜

7 月 20 日

题单(去重后 6 题)

来源题号 / 题名(全部可点)
作业P2865 [USACO06NOV] Roadblocks G
作业2384 最短路计数
作业P10947 [BAPC 2006 Qualification] Sightseeing
作业P1063B Labyrinth
作业P2850 [USACO06DEC] Wormholes G
作业P1205B Shortest Cycle

知识点

Code

P2865 Roadblocks G
void di(long long q){
    memset(dis,0x3f3f3f3f3f3f3f3f,sizeof(dis));
    dis[q][0]=0;
    pq.push({0,q});
    while(!pq.empty()){
        long long u=pq.top().x,d=pq.top().s;
        pq.pop();
        if(d>dis[u][1]) continue;
        for(int i=0;i<tree[u].size();i++){
            long long r=tree[u][i].r,v=tree[u][i].v;
            if(dis[r][0]>d+v){
                dis[r][1]=dis[r][0];
                dis[r][0]=d+v;
                pq.push({dis[r][0],r});
            }else if(dis[r][1]>d+v&&d+v>dis[r][0]){
                dis[r][1]=d+v;
                pq.push({dis[r][1],r});
            }else if(dis[r][1]>d+v&&d+v>dis[r][0]){
                dis[r][1]=d+v;
                pq.push({dis[r][1],r});
            }
        }
    }
}

7 月 21 日

题单(去重后 4 题)

来源题号 / 题名(全部可点)
比赛 + 订正作业A 比较 · 3104 比较(订正)
比赛 + 订正作业B 多边形 · 3100 多边形(订正)
比赛 + 订正作业C 传送 · 3101 传送(订正)
比赛 + 订正作业D 项链 · 3102 项链(订正)

知识点

Code

A 比较
	int n; cin >> n;
	string F, Y;cin >> F >> Y;
	cout << (F < Y ? "F" : (F == Y ? "-1" : "Y"));
B 多边形
	while(T--){
		int n; cin >> n;
			int cnt = 0, maxn = 0;
			for(int i = 1;i <= n;i++){
				int a;cin >> a;
				cnt += a;maxn = max(maxn, a);
			}
			if(cnt - maxn <= maxn) cout << "NO\n";
			else cout << "YES\n";
	}
C 传送
    for (int i = n; i >= 1; i--) {
//        for (int j = i + 1; j <= n; j++) {
//            if (a[i] > a[j])
//                f[i] = max(f[i], f[j] + 1);
//        }
//		f[i] = maxf[a[i] - 1] + 1;
		f[i] = qry(1, 1, a[i] - 1) + 1;
//		maxf[a[i]] = max(maxf[a[i]], f[i]);
		mdy(1, 1, INF, a[i], f[i]);
D 项链
int solve(int t[]) {
    memset(dp, 0, sizeof(dp));

    for(int i = 1; i <= n; i++) {
        dp[i][i] = 1;
    }

    for(int len = 2; len <= n; len++) {
        for(int l = 1; l + len - 1 <= n; l++) {
            int r = l + len - 1;

            dp[l][r] = dp[l + 1][r] + 1;

            for(int k = l + 1; k <= r; k++) {
                if(t[l] == t[k]) {
                    int now = dp[k][r];

                    if(k > l + 1) {
                        now += dp[l + 1][k - 1];
                    }

                    dp[l][r] = min(dp[l][r], now);
                }
            }
        }
    }

普转提20260721模拟赛:复盘

题目顺序:T1 = A 比较;T2 = B 多边形;T3 = C 传送;T4 = D 项链

项目 T1 T2 T3 T4
涉及算法标签 模拟?? 数学 线段树优化DP(最长上升子序列) 区间DP
得分 100 100 100 100
错误原因 - - - -
正确解法核心 同上 同上 同上 同上
以前做过的同类型题 ?? 最长上升子序列(基础版)(大数据版) 【CQOI2007】涂色
今天最大的教训认真
需要补的知识漏洞无!

7 月 22 日

题单(去重后 7 题)

来源题号 / 题名(全部可点)
作业3105 【模板】树的直径
作业P14D Two Paths
作业P3629 [APIO2010] 巡逻
作业P1395 会议
作业P3379 【模板】最近公共祖先(LCA)
作业P4281 [AHOI2008] 紧急集合 / 聚会
作业P3128 [USACO15DEC] Max Flow P

知识点

Code

P3379 最近公共祖先(LCA)
int find(int u) {
    if (u == fa[u])
        return u;
    return fa[u] = find(fa[u]);
}
void tarjan(int u) {
    vis[u] = 1;
    for (int v : e[u]) {
        if (!vis[v]) {
            tarjan(v);
            fa[v] = u;
        }
    }
    for (PII q : qry[u]) {
        int v = q.fi, i = q.se;
        if (vis[v])
            ans[i] = find(v);
    }
}

7 月 23 日

题单(去重后 8 题)

来源题号 / 题名(全部可点)
比赛 + 订正作业A 求和 · P8772 求和(订正)
比赛 + 订正作业B 拜年 · P5764 拜年(订正)
比赛 + 订正作业C 最大生成树 · P9488 最大生成树(订正)
比赛 + 订正作业D 序列操作 · P11208 序列操作(订正)
比赛 + 订正作业E 摆靶子 · P4388 摆靶子(订正)
比赛F 树
比赛G 简单的询问
比赛H 砝码称重

知识点

Code

A 求和
	int t = 0;
	for(int i = n;i >= 1;i--){
		t += x[i] * cnt;
		cnt += x[i];
	}
	cout << t;
B 拜年
    for(int i = 0; i < 6; i++) {
        dijkstra(p[i], i);
    }

    int a[5] = {1, 2, 3, 4, 5};
    int ans = INF;

    do {
        int sum = d[0][a[0]];

        for(int i = 1; i < 5; i++) {
            sum += d[a[i - 1]][a[i]];
        }

        ans = min(ans, sum);
    } while(next_permutation(a, a + 5));
C 最大生成树
    for(int i = n / 2;i >= 1;i--){
        int x = find(i);

        for(int j = 1;j <= cnt and prime[j] <= n / i;j++){
            int y = find(i * prime[j]);

            if(x == y) continue;

            fa[y] = x;
            ans += i;
        }
    }
D 序列操作
    int sum = 0;


    for(int i = 1;i <= n;i++){
        if(p[i] < n){
		    sum += qry(rt1, 1, n, p[i] + 1, n);
		}
        mdy(rt1, 1, n, p[i], 1);
    }

    for(int i = 1;i <= n;i++){
        mdy(rt2, 1, n, i, 1);
    }

    int ans = sum;

    for(int x = 1;x <= n;x++){
        int cnt = 0;
		if(pos[x] > 1) cnt = qry(rt2, 1, n, 1, pos[x] - 1);

        sum -= cnt;
//        cout << x << ' ' << cnt << ' ' << sum << '\n';
        mdy(rt2, 1, n, pos[x], -1);

        ans = min(ans, x + sum);
    }
E 摆靶子
int calc(int k) {
    if(k == 1) return 1;
    return phi[k + 1] / 2;
}

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);

    cin >> n;

    init(n + 1);

    int ans = 0;

    for(int i = 1;i <= n / i;i++) {
        if(n % i != 0) continue;

        ans += calc(i);

        if(i != n / i) {
            ans += calc(n / i);
        }
    }
G 简单的询问
void add1(int p) {
    anss += cnt2[a[p]];
    cnt1[a[p]]++;
}

void del1(int p) {
    cnt1[a[p]]--;
    anss -= cnt2[a[p]];
}

void add2(int p) {
    anss += cnt1[a[p]];
    cnt2[a[p]]++;
}

void del2(int p) {
    cnt2[a[p]]--;
    anss -= cnt1[a[p]];
}

    cin >> q;
    for (int i = 1; i <= q; i++) {
        int l1, r1, l2, r2;
        cin >> l1 >> r1 >> l2 >> r2;

        add_query(r1, r2, i, 1);
        add_query(l1 - 1, r2, i, -1);
        add_query(r1, l2 - 1, i, -1);
        add_query(l1 - 1, l2 - 1, i, 1);
    }

    sort(e + 1, e + tot + 1, cmp);

    int nowl = 0, nowr = 0;

    for (int i = 1; i <= tot; i++) {
        int l = e[i].l, r = e[i].r;

        while (nowl < l) add1(++nowl);
        while (nowl > l) del1(nowl--);
        while (nowr < r) add2(++nowr);
        while (nowr > r) del2(nowr--);

        ans[e[i].id] += e[i].k * anss;
    }

20260723周赛:复盘

题目顺序:T1 = A 求和;T2 = B 拜年;T3 = C 最大生成树;T4 = D 序列操作;T5 = E 摆靶子;T6 = F 树;T7 = G 简单的询问;T8 = H 砝码称重

项目 T1 T2 T3 T4 T5 T6 T7 T8
涉及算法标签 模拟 Dijkstra+全排列 并查集+欧拉筛+推导 线段树优化模拟(?) 数学推导+phi函数 - 莫队+二维前缀和 -
得分 100 100 100 100 0 0 0 0
错误原因 - - - - □ 时间不够 □ 时间不够 □ 时间不够 □ 时间不够
正确解法核心 同上 同上 同上 同上 同上 - 同上 -
以前做过的同类型题 无所谓,, 非负权单源最短路 【并查集】亲戚 + 再求素数 逆序对 Longge 的问题 - 小B的询问 -
今天最大的教训不要死磕一道题不看后面的题,尤其是IOI赛制!
需要补的知识漏洞换根DP??