传送门:https://acm.ecnu.edu.cn/problem/list/?source=2017 计算机系暑期夏令营机考
中文题不写题面了
我不知道我第一次打开界面为啥题号是倒着的,于是先看了“送分题”,然后按序号开的题,我竟反而觉得送分题真的送分题
有两题还没做,先放放
idea:
挺裸的莫队
直接抄的y总板子改了改
甚至觉得这题比后面的简单
code:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 500010;
int n, m, len;
int w[N], cnt[N];
LL ans[N];
struct Query
{
int id, l, r;
}q[N];
vector<int> nums;
int get(int x)
{
return x / len;
}
bool cmp(const Query& a, const Query& b)
{
int i = get(a.l), j = get(b.l);
if (i != j) return i < j;
return a.r < b.r;
}
void add(int x, LL& res)
{
if(cnt[x] == 2) res--;
cnt[x] ++ ;
if(cnt[x] == 2) res ++;
// res = max(res, (LL)cnt[x] * nums[x]);
}
int main()
{
scanf("%d%d", &n, &m);
len = sqrt(n);
for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]), nums.push_back(w[i]);
sort(nums.begin(), nums.end());
nums.erase(unique(nums.begin(), nums.end()), nums.end());
for (int i = 1; i <= n; i ++ )
w[i] = lower_bound(nums.begin(), nums.end(), w[i]) - nums.begin();
for (int i = 0; i < m; i ++ )
{
int l, r;
scanf("%d%d", &l, &r);
q[i] = {i, l, r};
}
sort(q, q + m, cmp);
for (int x = 0; x < m;)
{
int y = x;
while (y < m && get(q[y].l) == get(q[x].l)) y ++ ;
int right = get(q[x].l) * len + len - 1;
// 暴力求块内的询问
while (x < y && q[x].r <= right)
{
LL res = 0;
int id = q[x].id, l = q[x].l, r = q[x].r;
for (int k = l; k <= r; k ++ ) add(w[k], res);
ans[id] = res;
for (int k = l; k <= r; k ++ ) {
if(cnt[w[k]] == 2) res--;
cnt[w[k]] -- ;
if(cnt[w[k]] == 2) res++;
}
x ++ ;
}
// 求块外的询问
LL res = 0;
int i = right, j = right + 1;
while (x < y)
{
int id = q[x].id, l = q[x].l, r = q[x].r;
while (i < r) add(w[ ++ i], res);
LL backup = res;
while (j > l) add(w[ -- j], res);
ans[id] = res;
while (j < right + 1) {
cnt[w[j ++ ]] -- ;
}
res = backup;
x ++ ;
}
memset(cnt, 0, sizeof cnt);
}
for (int i = 0; i < m; i ++ ) printf("%lld\n", ans[i]);
return 0;
}
我随机不过去啊可恶
看到有人随机过了可能是我随的不太好
待补充
礼问正解是啥
idea:
相当于两种操作,1-对区间+1,2-询问总体最大值
离线操作然后离散化+差分
code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int N = 700;
struct no {
int op;
int num;
};
vector<no> ques;
vector<int> vec;
ll pre[N];
signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
string s;
cin >> s >> s;
int x;
cin >> x;
vec.push_back(x);
vec.push_back(x - 1);
vec.push_back(x + 1);
if (s == "<") {
ques.push_back({1, x});
} else if (s == "<=") {
ques.push_back({2, x});
} else if (s == "=") {
ques.push_back({3, x});
} else if (s == ">=") {
ques.push_back({4, x});
} else if (s == ">") {
ques.push_back({5, x});
}
}
vec.push_back(-inf), vec.push_back(inf);
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(), vec.end()), vec.end());
for (auto[op, num] : ques) {
int x = lower_bound(vec.begin(), vec.end(), num) - vec.begin();
if (op == 1) { // <
pre[1]++;
pre[x]--;
} else if (op == 2) { // <=
pre[1]++;
pre[x + 1]--;
} else if (op == 3) { // =
pre[x]++;
pre[x + 1]--;
} else if (op == 4) { // >=
pre[x]++;
// pre[vec.size()]--;
} else if (op == 5) { // >
pre[x + 1]++;
}
}
int ans = -1;
int sum = 0;
int siz = vec.size() - 1;
for (int i = 0; i <= siz; ++i) {
sum += pre[i];
ans = max(ans, sum);
}
cout << ans << endl;
return 0;
}
idea:
以l、r表示上下界,考虑0到r之间1个数最多的数时,1个数起码是r二进制位数-1(可以将r二进制1最高位变成0然后后面全赋成1)
加上下界,从高位到低位遍历,如果上下界从高位到低位开头一段的二进制一样,这段其实可以不考虑
对于剩下的部分,最坏情况就是将剩余最高位赋值成0,后面全1,特判能不能直接全1
code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
ll T;
cin >> T;
for (ll ttt = 1; ttt <= T; ++ttt) {
cout << "Case " << ttt << ": ";
ll l, r;
cin >> l >> r;
ll pos = 0;
ll res = 0;
for (ll i = 63; i >= 0; --i) {
if (((l >> i) & 1ll) + ((r >> i) & 1ll) == 1ll) {
pos = i;
break;
} else {
res += ((l >> i) & 1ll) * (1ll << i);
}
}
bool flag = 1;
for (int i = pos - 1; i >= 0; --i) {
if (((r >> i) & 1ll) == 0) {
flag = 0;
break;
}
}
if (flag) res += (r & ((1ll << (pos + 1)) - 1));
else res += (1ll << (pos)) - 1ll;
// cerr << pos << " " << (r & ((1ll <<( pos +1 )) - 1));
cout << res << endl;
}
}
idea:
分奇偶dp
code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 1e7 + 10;
ll dp[N];
signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
ll n, x, y;
cin >> n >> x >> y;
memset(dp, 0x3f, sizeof dp);
dp[0] = 0;
dp[1] = x;
for (ll i = 2; i <= n; ++i) {
if (i & 1) {
dp[i] = min(dp[i], dp[i - 1] + x);
dp[i] = min(dp[i], dp[i / 2] + y + x);
dp[i] = min(dp[i], dp[i / 2 + 1] + y + x);
} else {
dp[i] = min(dp[i], dp[i - 1] + x);
dp[i] = min(dp[i], dp[i / 2] + y);
}
}
cout << dp[n] << endl;
return 0;
}