2026-02-09~02-12 hetao1733837 的刷题记录

2026-02-09~02-12 hetao1733837 的刷题记录

02-09

LGP4447 [AHOI2018初中组] 分组

原题链接:[AHOI2018初中组] 分组

分析

啊?这咋二分?转变一下维度思考一下......看一下别人的代码......今天我一定要跑步!

?很......二分在哪?

正解

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
map<int, int> buc; 
priority_queue<int, vector<int>, greater<int>> q[N];
int n, a[N], tp;
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    for (int i = 1; i <= n; i++){
        cin >> a[i];
    }
    sort(a + 1, a + n + 1);
    for (int i = 1; i <= n; i++){
        if (buc[a[i]] == 0){
            buc[a[i]] = ++tp; 
        }
        if (buc[a[i] - 1] == 0 || q[buc[a[i] - 1]].empty()){
            q[buc[a[i]]].push(1);
        } 
        else{
            int tmp = q[buc[a[i] - 1]].top() + 1; 
            q[buc[a[i] - 1]].pop(); 
            q[buc[a[i]]].push(tmp);
        }
    }
    int ans = 0x3f3f3f3f;
    for (int i = 1; i <= n; i++){
        if (!q[buc[a[i]]].empty()){
            ans = min(ans, q[buc[a[i]]].top());
        }
    }
    cout << ans;
    return 0;
}

02-10

CF868F Yet Another Minimization Problem

原题链接1:CF868F Yet Another Minimization Problem

原题链接2:F. Yet Another Minimization Problem

分析

这个真的是凸的吗?分治和 DP 的结合......

还是有点太困难了。那么,从暴力转移入手,设 d p i , j dp_{i,j} dpi,j 表示考虑到了位置 i i i,分成了 j j j 段的最小花费,转移显然。

然后各种分治优化......并未看懂吧......

hyw?

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100005, K = 25;
const long long INF = 1e18;
int n, k, a[N];
int cnt[N];
long long dp[N][K];
int l, r, p;
long long sum = 0;
long long calc(int s, int t){
    while (l > s){
        l--;
        sum += cnt[a[l]];
        cnt[a[l]]++;
    }
    while (r < t){
        r++;
        sum += cnt[a[r]];
        cnt[a[r]]++;
    }
    while (l < s){
        cnt[a[l]]--;
        sum -= cnt[a[l]];
        l++;
    }
    while (r > t){
        cnt[a[r]]--;
        sum -= cnt[a[r]];
        r--;
    }
    return sum;
}
void solve(int L, int R, int ml, int mr){
    int mid = (L + R) >> 1;
    long long mn = INF;
    int tl = max(1LL, ml), tr = min(mid, mr);
    int pos = tl;
    for (int i = tl; i <= tr; i++){
        long long tmp = dp[i - 1][p - 1] + calc(i, mid);
        if (tmp < mn){
            mn = tmp;
            pos = i;
        }
    }
    dp[mid][p] = mn;
    if (L == R) 
        return;
    solve(L, mid, ml, pos);
    solve(mid + 1, R, pos, mr);
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> k;
    for (int i = 1; i <= n; i++){
        cin >> a[i];
    }
    for (int i = 0; i <= n; i++){
        for (int j = 0; j <= k; j++){
            dp[i][j] = INF;
        }
    }
    dp[0][0] = 0;
    p = 1;
    while (p <= k){
        l = 1, r = 0;
        sum = 0;
        memset(cnt, 0, sizeof(cnt));
        solve(1, n, 1, n);
        p++;
    }
    cout << dp[n][k];
    return 0;
}

还是太困难了/ll

02-11

LGP3803 【模板】多项式乘法(FFT)

原题链接:【模板】多项式乘法(FFT)

分析

DeepSeek 聊了很久,感觉好了一些吧......其实没看懂这个讲的是啥,但是还是决定整一下板子......

正解

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 4000005;
const double PI = acos(-1.0);
struct node{
	double x, y;
	node (double tx = 0, double ty = 0){
		x = tx;
		y = ty;
	}
}a[N], b[N];
node operator+(node tx, node ty){
	return node(tx.x + ty.x, tx.y + ty.y);
}
node operator-(node tx, node ty){
	return node(tx.x - ty.x, tx.y - ty.y);
}
node operator*(node tx, node ty){
	return node(tx.x * ty.x - tx.y * ty.y, tx.x * ty.y + tx.y * ty.x);
}
void FFT(int lim, node *k, int tp){
	if (lim == 1)
		return ;
	node t1[lim >> 1], t2[lim >> 1];
	for (int i = 0; i < lim; i += 2){ 
		t1[i >> 1] = k[i]; 
		t2[i >> 1] = k[i + 1]; 
	}
	FFT(lim >> 1, t1, tp);
	FFT(lim >> 1, t2, tp);
	node wn = node(cos(2.0 * PI / lim), tp * sin(2.0 * PI / lim));
	node w = node(1, 0);
	for (int i = 0; i < (lim >> 1); i++, w = w * wn){
		k[i] = t1[i] + w * t2[i]; 
		k[i + (lim >> 1)] = t1[i] - w * t2[i]; 
	}
}
int n, m;
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i = 0; i <= n; i++){
		cin >> a[i].x;
		a[i].y = 0;
	}
	for (int i = 0; i <= m; i++){
		cin >> b[i].x;
		b[i].y = 0;
	}
	int lim = 1;
	while (lim <= n + m){
		lim <<= 1;
	}
	FFT(lim, a, 1);
	FFT(lim, b, 1);
	for (int i = 0; i < lim; i++){
		a[i] = a[i] * b[i];
	}
	FFT(lim, a, -1);
	for (int i = 0; i <= n + m; i++){
		cout << (int)(a[i].x / lim + 0.5) << " ";
	}
}

02-12

LGP7831 [CCO 2021] Travelling Merchant

原题链接:[CCO 2021] Travelling Merchant

分析

似乎,对于每一个点,我找到图上一个最小环就结了?咦,这不是个贪吗?哦,就每次在所有出边里走?这么简单?套一个类似拓扑的东西,就没了......

正解

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
int n, m, d[N], ans[N];
struct node{
    int a, b, r, p;
}inp[N];
bool cmp(node x, node y){
    return x.r < y.r;
}
vector<int> e[N];
queue<int> q;
bool vis[N];
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m;
    for (int i = 1; i <= m; i++){
        cin >> inp[i].a >> inp[i].b >> inp[i].r >> inp[i].p;
        d[inp[i].a]++;
    }
    sort(inp + 1, inp + m + 1, cmp);
    for (int i = 1; i <= m; i++){
        e[inp[i].b].push_back(i);
    }
    for (int i = 1; i <= n; i++){
        if (!d[i]){
            q.push(i);
        }
    }
    memset(ans, 0x3f, sizeof(ans));
    for (int i = m; i >= 1; i--){
        while (!q.empty()){
            int u = q.front();
            q.pop();
            for (auto v : e[u]){
                if (vis[v])
                    continue;
                vis[v] = 1; 
                d[inp[v].a]--;
                if (!d[inp[v].a]){
                    q.push(inp[v].a);
                }
                if (ans[u] != 0x3f3f3f3f){
                    ans[inp[v].a] = min(ans[inp[v].a], max(inp[v].r, ans[u] - inp[v].p));
                }
            }
        }
        if (!vis[i]){
            vis[i] = 1;
            d[inp[i].a]--;
            if (!d[inp[i].a])
                q.push(inp[i].a);
            ans[inp[i].a] = min(ans[inp[i].a], inp[i].r);
        }
    }
    for (int i = 1; i <= n; i++){
        if (ans[i] != 0x3f3f3f3f){
            cout << ans[i] << " ";
        }
        else{
            cout << -1 << " ";
        }
    }
}

[AGC009C] Division into Two

原题链接1:[AGC009C] Division into Two

原题链接2:C - Division into Two

分析

上了个厕所......依旧感谢一下 DeepSeek !思考怎么做......不考虑时间的话......咦,我们可不可以这样设 DP ,就是设 d p i , j dp_{i,j} dpi,j 表示(这个在离散化意义下似乎比较好说明) A 的最大元素为 s i s_i si,B 为 s j s_j sj,的序列划分数那么,转移即为......

其实我也不知道......但是,我们似乎可以再次嵌套一个二分......思考一下......好的,优化一维,因为是个划分,所以不属于 A 则必定属于 B ,那么留下一维,然后另一维同样二分出来,找到某个区间可以转移,即同时满足 AB 的限制,直接拿下......细节方面......思考一下......然后拿一个前缀和......甚至不用二分,由于单调性,甚至掏一个指针就能过!

正解

cpp 复制代码
#include <bits/stdc++.h>
#define int long long
#define mod 1000000007
using namespace std;
const int N = 100005;
int n, A, B, s[N], dp[N];
int sum[N];
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> A >> B;
	if (A < B)
		swap(A, B);
	for (int i=1;i<=n;i++){
		cin>>s[i];
	}
	for(int i=3;i<=n;i++){
		if(s[i]-s[i-2]<B){
			cout << 0 << '\n';
			return 0;
		}
	}
	dp[0] = sum[0] = 1;
	int l = 0, r = 0;
	for (int i = 1; i <= n; i++){
		while (r < i && s[i] - s[r + 1] >= A)
			r++;
		if (l <= r) 
			dp[i] = sum[r] - (l == 0 ? 0ll : sum[l - 1]);
		dp[i] = (dp[i] % mod + mod) % mod;
		sum[i] = (sum[i - 1] + dp[i]) % mod;
		if (i > 1 && s[i] - s[i - 1] < B)
			l = i - 1;
	}
	int ans = 0;
	for (int i = n; ~i; i--){
		ans = (ans + dp[i]) % mod;
		if (i < n && s[i + 1] - s[i] < B)
			break;
	}
	cout << ans << '\n';
}

不管了,我要回去学 BO

反思一下......我应该没有做错什么,或许不完美......我要回生竞那边了。

相关推荐
ADDDDDD_Trouvaille2 小时前
2026.2.12——OJ72-74题
c++·算法
励ℳ2 小时前
机器学习-LASSO算法指南
人工智能·算法·机器学习
梵刹古音2 小时前
【C++】函数重写
开发语言·c++
Titan20242 小时前
C++异常学习笔记
c++·笔记·学习
Vic101012 小时前
算法D1-20260212:双指针专题
java·数据结构·算法
仟濹2 小时前
【算法打卡day7(2026-02-12 周四)算法:BFS and BFS】10__卡码网110_字符串迁移, 11_卡码网105_有向图的完全连通
算法·深度优先·dfs·bfs·宽度优先
935962 小时前
机考24 翻译18 单词11
c语言·数据结构·算法
柒儿吖3 小时前
DDlog 高性能异步日志库在 OpenHarmony 的 lycium 适配与分步测试
c++·c#·openharmony