Akane-Weekly #1NOIP 十连测 (1)

Akane-Weekly #1:NOIP 十连测 (1)

C.

简要题意:

黑板上有 \(n\) 个数,每次擦掉两个,换成两个的异或值并写上,有一次特殊的操作,可以将黑板上任意一个数 \(+1\) ,求执行恰好一次操作后黑板上剩余数的最大值。

\(n \le 2e5\)

Solution:

如果不加上 \(+1\) 操作,那最终值是固定的,怎么样通过 \(+1\) 增加答案呢?发现可以找到一个形如 \(1\dots 0 11111\)

的形式的数, \(+1\) 之后可以进位到上一位,增加贡献。考虑暴力枚举这个 $0 $ 的位置,暴力操作即可。

具体实现的时候,我们可以从低位往高位反着搞一个线性基,每次枚举 \(0\) 的位置 \(d\) 的位置的时候,把低位所有能取则取,保证取得数尽量凑到 \((1<<d)-1\) 即可。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[1000100];
int p[63],d[63];
bool vis[1000100];
void insert(int x){
	for(int i=0;i<63;i++){
	//	cout<<(x>>i)<<endl;
		if(!(x&(1ll<<i))) continue;
	//	cout<<id<<" "<<i<<" "<<x<<" "<<p[i]<<endl;
		if(!p[i]){
			p[i]=x;
			break;
		}
		x^=p[i];
	}
}
signed main(){
//	freopen("ex_tea4.in","r",stdin);
//	freopen("ex_tea.out","w",stdout);
	int tt=clock();
	int n;
	scanf("%lld",&n);
	int ans=0;
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		insert(a[i]);
		ans^=a[i];
	}
	int tot=ans;
	for(int i=0;i<63;i++){
	//	cout<<p[i]<<endl;
		int x=(1ll<<i)-1;
		for(int j=0;j<63;j++){
			if(!(x&(1ll<<j))) continue;
			x^=p[j];
		}
		x^=(1ll<<i)-1;
	//	cout<<p[i]<<endl;
		ans=max(ans,tot^x^(x+1));
	}
	printf("%lld\n",ans);
//	cout<<clock()-tt;
}

D.

简要题意:

给定一个(点)仙人掌,每条边有两个权值 \((a,b)\) ,定义一个生成树的权值为 \(\sum E_a \times \sum E_b\)\(\{E\}\) 表示被选中的边集,求最小生成树。\(n\le 2e5\)

Solution:

考虑每没一个生成树对应二维坐标的一个点 \((\sum E_a, \sum E_b)\) 。发现每个环都要断开一条边,而这些操作是独立的,对于两个环 \(a,b\) ,假设他们的生成树有点 \((X_a,Y_a)\)\((X_b,Y_b)\) ,则考虑它们两个拼起来的生成树,发现可以用 \((X_a+Y_a,X_b+Y_b)\) 。所以把环拆开考虑即可。

考虑什么样的点是 \(MST\) ,发现这些点要在一个下凸包上,所以做完每一个换就维护一个下凸包。把多个环拼起来的时候需要使用闵可夫斯基和,当环很多的时候就用分治优化,每次再做闵可夫斯基和即可。

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct node{
	int v,a,b;
};
int low[2000010],dep[2000100];
int tot;
int idx;
int top;
int st[2000010];
vector<node> g[1000100];
vector<int> ans[1000010];
vector<int> an[1000010];
int n,m;
void dfs(int u,int fa){
	int so=0;
	st[++top]=u;
	low[u]=dep[u]=++idx;
	for(int i=0;i<g[u].size();i++){
		int v=g[u][i].v;
		if(v==fa) continue;
		if(dep[v]==0){
			so++;
			dfs(v,u);
			low[u]=min(low[u],low[v]);
			if(low[v]>=dep[u]){
				tot++;
				ans[tot].push_back(u);
				do{
					ans[tot].push_back(st[top]);
				}while(st[top--]!=v);
			}
		}else{
			low[u]=min(low[u],dep[v]);
		}
	}
	if(u==fa&&so==0){
		ans[++tot].push_back(u);
	}
}
struct point{
	int x,y;
	friend point operator + (point x,point y){
		return point{x.x+y.x,x.y+y.y};
	}
	friend bool operator == (point x,point y){
		return x.x==y.x&&x.y==y.y;
	}
	friend bool operator <(point x,point y){
		if(x.x==y.x) return x.y<y.y;
		return x.x<y.x;
	}
	friend point operator -(point x,point y){
		return point{x.x-y.x,x.y-y.y};
	}
};
int cross(point x,point y){
	return x.x*y.y-x.y*y.x;
}
vector<point> Convex[400010]; 
vector<point> ansr;
void Get_Convex(int x){
	vector<point> pre;
	if(ans[x].size()==2) {
		Convex[x].push_back(point{0,0});
		return ;
	}
	for(int i=1;i<ans[x].size();i++){
		for(auto v:g[ans[x][i]]){
			if(v.v==ans[x][i-1]) pre.push_back(point{v.a,v.b});
		}
	}
	for(auto v:g[ans[x].back()]){
		if(v.v==ans[x][0]) pre.push_back(point{v.a,v.b});
	}
	sort(pre.begin(),pre.end());
	pre.erase(unique(pre.begin(),pre.end()),pre.end());
	for(int i=0;i<pre.size();i++){
		while(Convex[x].size()>=2&&cross(Convex[x].back()-Convex[x][Convex[x].size()-2],pre[i]-Convex[x][Convex[x].size()-2])>=0){
			Convex[x].pop_back();
		}
		Convex[x].push_back(pre[i]);
	}
}
vector<point> solve(int l,int r){
	if(l==r){
		return Convex[l];  
	}
	int mid=(l+r)>>1;
	auto ls=solve(l,mid),rs=solve(mid+1,r);
	vector<point> pre;
	pre.push_back(ls[0]+rs[0]);
	for(int i=1,j=1;i<ls.size()||j<rs.size();){
		if(i==ls.size()||(j!=rs.size()&&cross(rs[j]-rs[j-1],ls[i]-ls[i-1])<=0)){
			pre.push_back(ls[i-1]+rs[j]),j++;
		}else{
			pre.push_back(ls[i]+rs[j-1]),i++;
		}
	} 
	return pre;
}
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9')
        x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int sa,sb;
signed main(){
//	freopen("ex_carnation3.in","r",stdin);
//	freopen("1.out","w",stdout);
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int x,y,a,b;
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>x>>y>>a>>b;
		sa+=a,sb+=b;
		g[x].push_back(node{y,a,b});
		g[y].push_back(node{x,a,b});
	}
	dfs(1,1);//Tarjan for v_dcc;
	for(int i=1;i<=tot;i++){
		Get_Convex(i);
	}
	ansr=solve(1,tot);
	int mx=8e18;
	for(auto u:ansr){
		mx=min(mx,(sa-u.x)*(sb-u.y));
	}
	cout<<mx;
	return 0;
} 

posted @ 2023-09-02 22:47  ArizonaYYDS  阅读(40)  评论(1)    收藏  举报