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;
}

浙公网安备 33010602011771号