2025-11-18 hetao1733837的刷题记录

2025-11-18 hetao1733837的刷题记录

灵茶八题 - 子数组 ^w+

原题链接:灵茶八题 - 子数组 ^w+

分析

位运算是独立的,即每一位互不影响,所以,考虑每一位的贡献。

所以题目$\sum\limits_{l=1}{n}\sum\limits_{r=l}(a_l\bigoplus a_{l+1}\bigoplus ···\bigoplus a_{r-1} \bigoplus a_r)$

转化为$\sum\limits_{k=0}^{30}(cnt0_k\times cnt1_k)\times 2^k$

正解

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100005;
int a[N], sum[N];
int n;
signed main(){
    cin >> n;
    for (int i = 1; i <= n; i++){
        cin >> a[i];
        sum[i] = sum[i - 1] ^ a[i];
    }
    int ans = 0;
    for (int bit = 0; bit < 31; bit++){
        int cnt0 = 1, cnt1 = 0;
        for (int i = 1; i <= n; i++){
            if (sum[i] >> bit & 1){
                cnt1++;
            } 
            else{
                cnt0++;
            }
        }
        ans += cnt0 * cnt1 * (1 << bit);
    }
    cout << ans;
    return 0;
}

幽默的世界。

原题链接:幽默的世界。

分析

思路正确!幽默序列即为前面都是非正数,最后一个是正数,和为正数,好的,继续……不会了?

那么,对于每个正数向前找非正数,且区间和为正数,若找到了$a$个非正数,贡献为$a+1$,这一步预处理即可。

但是,如果询问区间将以正数为划分的区间劈开怎么办?那么最后一个是不会有贡献的,再处理左端点即可。

正解

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 200005;
int n, q, a[N];
long long sum[N];
int l, r;
int pos[N], top;
int w[N];
int work(int k){
    int l = 1, r = top;
    while (l <= r){
        int mid = (l + r) >> 1;
        if (pos[mid] > k)
            r = mid - 1;
        else
            l = mid + 1;
    }
    return r;
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> q;
    for (int i = 1; i <= n; i++){
        cin >> a[i];
    }
    int tot = 0;
    int p;
    for (int i = n; i; i--){
        if (a[i] > 0){
            p = i;
            tot = 0;
            pos[++top] = p;
        }
        tot += a[i];
        if  (tot > 0)
            w[p]++;
    }
    sort(pos + 1, pos + top + 1);
    for (int i = 1; i <= top; i++)
        sum[i] = sum[i - 1] + w[pos[i]];
    while (q--){
        cin >> l >> r;
        int ans = 0;
        int L = work(l), R = work(r);
        if (pos[R] < l)
            goto O;
        if (pos[L] < l)
            ++L;
        ans = sum[R] - sum[L] + min(w[pos[L]], pos[L] - l + 1);
        O:cout << ans << '\n';
    }
}

[ABC203D] Pond

原题链接1:[ABC203D] Pond

原题链接2:D - Pond

分析

二分答案……嗯,我没看题。ber,单调性在哪?容我稍考。这能二分答案?咋的,二分中位数?确实如此,但是怎么$check$?交给题解。

操,数据范围$N\le 800$,当成$N\le 10^5$了。

那么,就可以$O(n^2)$check了。

写出来$j <= j$这辈子也是有了。

正解

#include <bits/stdc++.h>
using namespace std;
const int N = 805;
int n, k, a[N][N];
bool check(int x){
    int b[N][N], sum[N][N];
    memset(b, 0, sizeof(b));
    memset(sum, 0, sizeof(sum));
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= n; j++){
            if (a[i][j] > x)
                b[i][j] = 1;
            else
                b[i][j] = 0;
        }
    }
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= n; j++){
            sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + b[i][j];
        }
    }
    for (int i = 1; i + k - 1 <= n; i++){
        for (int j = 1; j + k - 1 <= n; j++){
            int tmp = sum[i + k - 1][j + k - 1] - sum[i - 1][j + k - 1] - sum[i + k - 1][j - 1] + sum[i - 1][j - 1];
            if (tmp < k * k / 2 + 1)
                return true;
        }
    }
    return false;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> k;
    int l = 0x3f3f3f3f, r = 0xc0c0c0c0;
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= n; j++){
            cin >> a[i][j];
            l = min(l, a[i][j]);
            r = max(r, a[i][j]);
        }
    }
    int ans = r;
    while (l <= r){
        int mid = (l + r) >> 1;
        if (check(mid)){
            ans = mid;
            r = mid - 1;
        }
        else{
            l = mid + 1;
        }
    }
    cout << ans;
    return 0;
}

CF1260D A Game with Traps

原题链接1:CF1260D A Game with Traps

原题链接2:1260D

分析

本来以为是二分答案+背包check,转头一看$N,M\le 10^5$吓哭了。稍考一下。时间越长似乎越优,所以我们最好把时间尽量用完,所以尽量拆除陷阱。

猜想:二分求得的是士兵的个数,check的是时间,而我们把士兵按照敏捷度排序,先二分找到允许最不敏捷士兵通过的陷阱,”你“去拆掉即可?再返回,加上带着这些士兵到达$n+1$的时间?复杂度大概是两个$log$?那二分答案在哪?

那不对啊,找到$d_i$之后没法确定最大的r啊,咋这么阴?

我要看题解!!!

哦,好像可以$O(n)$求最大$r_i$?我先he一下题解。

确实,我是糖糖,$O(k)$差分$check$是允许的。

正解

#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
int n, m, k, t;
int a[N];
int cha[N];
struct node{
	int l, r, d;
}inp[N];
bool check(int x){
	int lowest = a[x];
	memset(cha, 0, sizeof(cha));
	for (int i = 1; i <= k; i++){
		if (inp[i].d > lowest){
			cha[inp[i].l]++;
			cha[inp[i].r + 1]--;
		}
	}
	int lst = 0, sum = 0;
	for (int i = 1; i <= n + 1; i++){
		cha[i] += cha[i - 1];
		if (cha[i] != 0){
			sum += 3;
		}
		else{
			sum += 1;
		}
	}
	if (sum <= t)
		return true;
	return false;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> m >> n >> k >> t;
	for (int i = 1; i <= m; i++){
		cin >> a[i];
	}
	for (int i = 1; i <= k; i++){
		cin >> inp[i].l >> inp[i].r >> inp[i].d;
	}
	sort(a + 1, a + m + 1, greater<int>());
	int l = 0, r = m + 1;
	while (l < r){
		int mid = (l + r) >> 1;
		if (check(mid)){
			l = mid + 1;
		}
		else{
			r = mid;
		}
	}
	cout << max(0, r - 1);
}

还在In queue!

标准时间12:10:13交的,12:16:32才过!!!

LG2949 [USACO09OPEN] Work Scheduling G

原题链接:[USACO09OPEN] Work Scheduling G

分析

呃,你猜我理解了吗?并非。

正解

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100005;
int n;
struct node{
    int d, p;
}a[N];
bool cmp(node x, node y){
    return x.d < y.d;
}
priority_queue<int, vector<int>, greater<int>> q; 
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].d >> a[i].p;
    sort(a + 1, a + n + 1, cmp);
    int ans = 0;
    for (int i = 1; i <= n; i++){
        if (a[i].d > q.size()){ 
            ans += a[i].p;
            q.push(a[i].p); 
        }
        else if (!q.empty() && q.top() < a[i].p){
            ans += a[i].p - q.top();
            q.pop();
            q.push(a[i].p);
        }
    }
    cout << ans;
}

LG2107 小 Z 的 AK 计划

原题链接:小 Z 的 AK 计划

呃……依旧叹为观止……

正解

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 100005;
int n, m;
struct node{
	int x, t;
}a[N];
bool cmp(node p, node q){
	return p.x < q.x;
} 
priority_queue<int> q;
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i = 1; i <= n; i++){
		cin >> a[i].x >> a[i].t;
	}
	int ans = 0;
	sort(a + 1, a + n + 1, cmp);
	int sum = 0;
    int cnt = 0;
	for (int i = 1; i <= n; i++){
		sum += a[i].x - a[i - 1].x;
        q.push(a[i].t);
        cnt++;
        sum += a[i].t;
        while (!q.empty() && sum > m){
            cnt--;
            sum -= q.top();
            q.pop();
        }
        if (sum > m)
            break;
        ans = max(ans, cnt);
	}
	cout << ans;
}

LG3545 [POI 2012] HUR-Warehouse Store

原题链接:[POI 2012] HUR-Warehouse Store

分析

感觉反悔贪心更是一种玄学……非常类似正经贪心,只是决策稍微复杂一点?好……呃……

那么,本题其实就是尽可能满足每一位顾客,当每日进货量无法满足,取出大根堆堆顶,然后删删加加就没了?

正解

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 250005;
int a[N], b[N];
priority_queue<pair<int, int>> q;
bool vis[N];
int n;
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];
	for (int i = 1; i <= n; i++)
		cin >> b[i];
	int sum = 0, ans = 0;
	for (int i = 1; i <= n; i++){
		sum += a[i];
		if (sum < b[i] && !q.empty() && q.top().first > b[i]){
			vis[q.top().second] = 0;
			sum += q.top().first;
			q.pop();
			ans--;
		}
		if (sum >= b[i]){
			sum -= b[i];
			q.push({b[i], i});
			vis[i] = 1;
			ans++;
		}
	}
	cout << ans << '\n';
	for (int i = 1; i <= n; i++)
		if (vis[i])
			cout << i << " ";
}

posted on 2025-11-18 20:49  hetao1733837  阅读(9)  评论(0)    收藏  举报

导航