2023.9.9
- 赛时因为开了火车头喜提 \(0\) 分。
A
维护一个可重集,支持:
-
插入一个二元组。
-
删除一个二元组,保证之前存在。
-
给出二元组 \((x,y)\),问有多少个可重集内的二元组 \((a,b)\) 满足 \(x\oplus a>y\oplus b\).
\(m\le 2\times 10^5\),\(0\le x,y\le 10^{18}\).
容易想到 trie,有四个分叉记录 \(x,y\) 当前位的值。
然后思考一下怎么求答案。发现递归下去会导致一次查询的递归数为 \(O(m)\).
发现递归下去的当前位异或和与 \(x\oplus y\) 相同,于是考虑插入的时候只记录当前异或和的节点。
#include<bits/stdc++.h>
#define ll long long
#define N 200010
#define L 62
using namespace std;
ll read(){
ll x=0,w=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*w;
}
int s[N*L][2][2],h[N*L][2],tot,rt;
int opt;ll x,y;
#define g(x) (((x)>>d)&1)
void ins(int &r,int d){
if(d==-1)return;
s[r?r:r=++tot][g(x)][g(y)]+=3-opt*2;
ins(h[r][g(x^y)],d-1);
}
int qry(int r,int d){
if(!r||d==-1)return 0;
return s[r][!g(x)][g(y)]+qry(h[r][g(x^y)],d-1);
}
int main(){
int T=read();
while(T--){
opt=read(),x=read(),y=read();
if(opt!=3)ins(rt,L-1);
if(opt==3)printf("%d\n",qry(rt,L-1));
}
return 0;
}
B
有 \(n\) 个物品,第 \(i\) 个物品在 \(t\) 时刻的价值为 \(k_it+b_i\).
求一个最小的时刻 \(t\),满足选择至多 \(m\) 个物品的最大价值 \(\ge S\).
\(m\le n\le 10^6\),\(|b_i|\le 10^9\),\(|k_i|\le 10^6\),\(0\le S\le 10^{18}\).
考虑答案随着 \(t\) 的变化。
对于 \(\sum k<0\) 的,它们一定在某个时刻之前选最优。
对于 \(\sum k\ge 0\) 的可以成为 \(t\) 较大时的答案。
所以你发现这个函数是个 U 形的壳。
对于这个极值分成两部分求解。
- \(k<0\)
此时一定有 \(t=0\).
- \(k>0\)
可以直接二分一个 \(t\),把最大的 \(m\) 项加起来。
这一 part 是 \(O(n\log n\log V)\) 的,容易发现瓶颈在于排序。
nth_element
支持 \(O(n)\) 将把序列的前 \(k-1\) 小放在前 \(k-1\) 位,第 \(k\) 小放在第 \(k\) 位。
这个是 CSP-S2020 初赛的一个东西。
然后就做完了。
C
P9566 [SDCPC2023] Difficult Constructive Problem
给出一个 \(01\) 串,有通配符,问使得串中相邻不同字符对数恰好为 \(k\) 的字典序最小的字符串。
或判断无解。多测。
\(0\le k<n\le 10^5\),\(\sum n\le 10^6\).
有一档部分分是首尾都不为通配符。考虑从这个入手。
容易发现修改一位不会使得 \(cnt\) 的奇偶性改变。
可以求出 \(cnt\) 的上下界 \(mn,mx\).
那么如果 \(k\not\equiv cnt\space(\operatorname{mod}2)\) 或者 \(k\not\in[mn,mx]\) 无解。
实际上可以将首尾的 \(?\) 拆成 \(0\) 和 \(1\).
先令所有 \(?\) 为 \(0\),从后往前贪心构造。
当 \(cnt=k\) 时最优,直接输出。
当 \(cnt>k\) 时,令 \(?\) 所在的 \(101\rightarrow 111\).
当 \(cnt<k\) 时,令 \(?\) 所在的 \(000\rightarrow 010\).
不太好写。
D
对于树上的每个点,将其视为根,在树上选出 \(k\) 条从根开始的路径,最小化每个点到路径的最小距离乘上 \(w_i\) 之和。
\(n\le 2\times 10^5\),\(1\le k\le n\),\(1\le w_i\le 10^6\).
不思考,骗完部分分跑路。