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) 收藏 举报
浙公网安备 33010602011771号