CSP-S开小灶3
A. 世界冰球锦标赛
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline ull read(){
ull x = 0; char c = getchar();
while(c < '0' || c > '9')c = getchar();
do{x = (x << 1) + (x << 3) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
return x;
}
ull f[1050000], g[1050000], m, v[45], lg[1050000];
int n, n1, n2, c1, c2;
int main(){
n = read(), m = read();
n1 = n >> 1, n2 = n - n1;
for(int i = 1; i <= max(n1, n2); ++i)lg[1 << i] = i;
for(int i = 1; i <= n1; ++i)v[i] = read();
c1 = 1 << n1;
for(int i = 1; i < c1; ++i)f[i] = f[i xor (i & -i)] + v[lg[i & -i] + 1];
for(int i = 1; i <= n2; ++i)v[i] = read();
c2 = 1 << n2;
for(int i = 1; i < c2; ++i)g[i] = g[i xor (i & -i)] + v[lg[i & - i] + 1];
sort(f + 1, f + c1); sort(g + 1, g + c2);
ull ans = 0; int p2 = 0;
for(int i = c1 - 1; i >= 0; --i){
while(p2 < c2 && g[p2] + f[i] <= m)++p2;
ans += p2;
}
printf("%llu",ans);
return 0;
}
B. 滚
考场认为自己打了个暴力,结果是复杂度分析错了?
用莫队维护当前的 \(f_x\)
然后维护一下 \(cnt_{f_x}\)
(我的代码里这两个是反过来的)
每次询问扫 \(cnt\) 即可
为啥是对的 ?
因为每次处理了\(f_x\)相同的, 然后\(\sum f_x\)为区间长度(最大为 \(n\)) 也就是说,存在值不同的 \(f_x\) 最多 \(\sqrt n\) 个
找有值的 \(cnt\) 的过程我是爆扫,如果构造一下数据是过不了的, 因为复杂度不对
正解应该爆扫 \(<= \sqrt n\) 的,对大于的用桶排序维护一下
有不少人用 \(set\) 那个会在莫队移动上乘个 \(log\) 复杂度也不对
或者像 \(Lyin\) 大佬一样打个链表?
懒得打了, 反正 \(TLEcodes\) 都过了
勉强算是\(AK\)一次???????????
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 200005;
inline int read(){
int x = 0; char c = getchar();
while(c < '0' || c > '9')c = getchar();
do{x = (x << 1) + (x << 3) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
return x;
}
int a[maxn], w[maxn], n, m, bl[maxn], len, ans[maxn];
struct Q{
int l, r, k, id;
friend bool operator < (const Q &x, const Q &y){
return bl[x.l] == bl[y.l] ? x.r < y.r : x.l < y.l;
}
}q[maxn];
int cnt[maxn], f[maxn];
int query(int k, int sum){
int las = -0x3f3f3f3f, mx = -1;
for(int i = 1; sum; ++i)if(f[i]){
sum -= f[i] * i; if(las + k >= i)mx = max(mx, w[i]);
las = i;
}
return mx;
}
void add(int col){
if(cnt[col] > 0)--f[cnt[col]];
++f[++cnt[col]];
}
void del(int col){
--f[cnt[col]--];
if(cnt[col] > 0)++f[cnt[col]];
}
void solve(){
int l = 0, r = 0;
for(int i = 1; i <= m; ++i){
while(q[i].l < l)add(a[l - 1]), --l;
while(q[i].r > r)add(a[r + 1]), ++r;
while(q[i].l > l)del(a[l]), ++l;
while(q[i].r < r)del(a[r]), --r;
ans[q[i].id] = query(q[i].k, q[i].r - q[i].l + 1);
}
}
int main(){
n = read(), m = read();
for(int i = 1; i <= n; ++i)a[i] = read();
for(int i = 1; i <= n; ++i)w[i] = read();
for(int i = 1; i <= m; ++i)q[i].id = i, q[i].l = read(), q[i].r = read(), q[i].k = read();
len = sqrt(n);
for(int i = 1; i <= n; ++i)bl[i] = (i + len - 1) / len;
sort(q + 1, q + m + 1);
solve();
for(int i = 1; i <= m; ++i)printf("%d\n",ans[i]);
return 0;
}