去年XCPC补题记录
去年打的太区了,虽然莫名今年强了点,但是还是有点危险的说,不摆烂了
BYD去年就是打鸣潮打的,微微一闹很麻麻
2025 SH (单题质量展示清华实力,题目组合展现鹅腿美味)#
A#
先提一个小技巧,如何 O(1)判断 是否在 子树内?
使用dfn和out作比较即可。(我绝对不会说我的第一反应是倍增)
思路上,首先二分出深度。其次,考虑定位某层的点,考虑一次至少削掉一些东西。
G#
首先易得划分成不多于两个是不劣的
位运算一般很贪心,因为高位的意义大于剩下位数的总和
对高位贪心,若最高位1个数为奇数,一组即可(否则拆成奇+偶会导致最高位为0)
若1个数为偶数,则必须变成两组。 考虑 ,进行一些化简(注意符合的运算规则),最后得到一个最大异或和。
#include <bits/stdc++.h>
#define int long long
#define N 500005
using namespace std;
int a[N],p[65];
void insert(int k){
for (int i=59;i>=0;i--){
if (((k>>i)&1ll)==0){
continue;
}
if (p[i]==0){
p[i]=k;
break;
}
k^=p[i];
}
}
int getmax(){
int sum=0;
for (int i=59;i>=0;i--){
if ((sum^p[i])>=sum){
sum^=p[i];
}
}
return sum;
}
signed main (){
int T,n,maxn,xorsum=0,mp;
cin>>T;
while (T--){
memset(p, 0, sizeof(p));
maxn=-1ll;
xorsum=0;
cin>>n;
for (int i=1;i<=n;i++){
cin>>a[i];
xorsum^=a[i];
maxn=max(maxn,a[i]);
}
for (int i=59;i>=0;i--){
if (maxn>=(1ll<<i)){
mp=i;
break;
}
}
int count=0;
for (int i=1;i<=n;i++){
if ((a[i]>>mp)&1ll==1ll){
count++;
}
}
if (count%2==1){
cout<<xorsum<<endl;
}else{
for (int i=1;i<=n;i++){
insert(a[i]&(~xorsum));
}
cout<<getmax()<<endl;
}
}
return 0;
}