博客

去年XCPC补题记录

去年打的太区了,虽然莫名今年强了点,但是还是有点危险的说,不摆烂了

BYD去年就是打鸣潮打的,微微一闹很麻麻

2025 SH (单题质量展示清华实力,题目组合展现鹅腿美味)#

A#

先提一个小技巧,如何 O(1)判断 vv 是否在 uu 子树内?

使用dfn和out作比较即可。(我绝对不会说我的第一反应是倍增)

思路上,首先二分出深度。其次,考虑定位某层的点,考虑一次至少削掉一些东西。

G#

首先易得划分成不多于两个是不劣的

位运算一般很贪心,因为高位的意义大于剩下位数的总和

对高位贪心,若最高位1个数为奇数,一组即可(否则拆成奇+偶会导致最高位为0)

若1个数为偶数,则必须变成两组。 考虑 x异或y=sx{异或}y=s ,进行一些化简(注意符合的运算规则),最后得到一个最大异或和。

CSS67 行
#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;
} 



搜索文章

按标题、标签或摘要查找文章