首页 > 其他分享 >[省选联考 2024] 魔法手杖 题解

[省选联考 2024] 魔法手杖 题解

时间:2024-03-10 17:33:56浏览次数:14  
标签:pw min 省选 题解 mn mid ans fl 联考

首先有个很显然的 \(\mathcal O(nk^2)\) 的做法,即二分答案,然后 trie 树上判断。

对于 trie 树上一颗子树内的判定,考虑当前二分的 \(\text{mid}\) 这一位是 \(1\) 还是 \(0\) 以及 \(x\) 这一位填什么。

  • 对于 \(1\) 的情况,如果填 \(0\),那么右儿子仍然合法,左儿子中的数必须要放到集合 \(S\) 中。预处理出一个子树内 \(a\) 的最小值以及 \(b\) 的和,递归到右儿子继续求解。填 \(1\) 的情况类似。

  • 对于 \(0\) 的情况,如果填 \(0\),那么右儿子已经满足异或值 \(>\text{mid}\),递归到左儿子继续求解。填 \(1\) 的情况类似。

发现这种做法每个点只会被遍历一次,可以获得云斗 \(92\) & CCF \(72\) 分的好成绩。


优化的部分就简单了。

考虑怎么优化。发现可以把二分去掉,在子树内贪心考虑如果答案的当前位填 \(1\),剩下的位全填 \(0\) 是否有解,如果有解就填 \(1\),否则填 \(0\)。

发现判定可以用之前预处理出来的东西 \(\mathcal O(1)\) 做,每个点只会被遍历一次。所以时间复杂度 \(\mathcal O(nk)\),可以通过此题。

参考代码:

#include<bits/stdc++.h>
#define mxn 100003
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define rept(i,a,b) for(int i=a;i<b;++i)
#define drep(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
inline int read(){
    int x=0;char c=getchar();
    while(!isdigit(c))c=getchar();
    while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x;
}
inline __int128 read1(){
    __int128 x=0;char c=getchar();
    while(!isdigit(c))c=getchar();
    while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x;
}
inline void print(__int128 a){
    if(a>9)print(a/10);
    putchar(a%10+'0');
}
int c,T,n,m,k,b,sm,tot,f[mxn*120],t[mxn*120][2];
__int128 a,mn,pw[123],A[mxn],s[mxn*120];
void ins(){
    int p=0;
    drep(i,k-1,0){
        if(!t[p][(a>>i)&1])t[p][(a>>i)&1]=++tot,f[tot]=0,s[tot]=a;
        p=t[p][(a>>i)&1],f[p]=min(f[p]+b,m+1),s[p]=min(s[p],a);
    }
}
__int128 solve(__int128 mid,int x,int d,__int128 now,__int128 mn,int sum,bool fl){
    if(sum>m)return 0;
    if(d<0)return mid;
    __int128 ans=0;
    if(pw[d]-1+(fl&&t[x][1]?min(mn,s[t[x][1]]):mn)+now>=mid){
    	ans=max(ans,solve(mid+pw[d],fl?t[x][0]:0,d-1,now+pw[d],fl&&t[x][1]?min(mn,s[t[x][1]]):mn,min(sum+(fl?f[t[x][1]]:0),m+1),fl&&t[x][0]));
	}
    if(pw[d]-1+(fl&&t[x][0]?min(mn,s[t[x][0]]):mn)+now>=mid+pw[d]){
    	ans=max(ans,solve(mid+pw[d],fl?t[x][1]:0,d-1,now,fl&&t[x][0]?min(mn,s[t[x][0]]):mn,min(sum+(fl?f[t[x][0]]:0),m+1),fl&&t[x][1]));
	}
	if(ans)return ans;
	if(pw[d]-1+mn+now>=mid){
		ans=max(ans,solve(mid,fl?t[x][0]:0,d-1,now,mn,sum,fl&&t[x][0]));
	}
	if(pw[d+1]-1+mn+now>=mid){
		ans=max(ans,solve(mid,fl?t[x][1]:0,d-1,now+pw[d],mn,sum,fl&&t[x][1]));
	}
    return ans;
}
signed main(){
    c=read(),T=read();
    pw[0]=1;
    rep(i,1,120)pw[i]=pw[i-1]*2;
    while(T--){
        n=read(),m=read(),k=read();
        rep(i,0,tot)t[i][0]=t[i][1]=0;
        tot=0;
        sm=0,mn=pw[k];
        rep(i,1,n)A[i]=read1();
        rep(i,1,n){
            b=read(),a=A[i];
            ins();
            sm=min(sm+b,m+1),mn=min(mn,a);
        }
        if(sm<=m){
            print(mn+pw[k]-1);
            puts("");
            continue;
        }
        print(solve(0,0,k-1,0,pw[k],0,1));
        puts("");
    }
    return 0;
}

标签:pw,min,省选,题解,mn,mid,ans,fl,联考
From: https://www.cnblogs.com/zifanoi/p/18064459

相关文章

  • [省选联考 2024] 季风 题解
    \(\large\textbf{Statement.}\)求出最小的非负整数\(m\),使得:\[\left|x-\sum_{i=0}^{m-1}x_{i\bmodn}\right|+\left|y-\sum_{i=0}^{m-1}y_{i\bmodn}\right|\lemk\]\(\large\textbf{Solution.}\)考虑枚举\(m\bmodn\),然后求和就转化成了一段前缀和加上整个序列和的若......
  • Gym-101915D 题解
    D给定一张图,分为左右各\(P\)个点,左右各自内部是一个完全图,左右之间有\(m\)条边。求这个图的最大团。\(P\le20,m\leP^2\)。对于每个右部点,求出一个长度为\(20\)的二进制数,第\(i\)位是\(1\)表示它与左部第\(i\)点有连边。枚举右部点的子集\(S\),将它们的二进制数......
  • Acwing166 数独题解 - DFS剪枝优化
    166.数独-AcWing题库题意数独是一种传统益智游戏,你需要把一个9×9的数独补充完整,使得数独中每行、每列、每个3×3的九宫格内数字1∼9均恰好出现一次。请编写一个程序填写数独。思路搜索+剪枝(优化搜索顺序、位运算)优化搜索顺序:很明显,我们肯定是从当前能填合法......
  • [ABC219E] Moat 题解
    [ABC219E]Moat题解思路解析一眼看到输入数据只有\(4\)行\(4\)列,直接想到状压枚举。可以直接枚举所有护城河所包含起来的格子,判断是否连通以及判断是否包含住了所有村庄。判断连通我选择用洪水填充,随便选一个包含着的格子,若可以通过当前格移动到所有被包含格就说明连通。以......
  • ABC344G 题解
    ABC344G题解给定平面上\(n\)个点和\(q\)条直线,问对于每条线,有多少点在它上方。形式化的,对于直线\(y=ax+b\)统计有多少点\((x,y)\)满足\(y\geax+b\),即\(-ax+y\geb\)。故我们可以将所有点按照\(-ax+y\)排序,从而利用二分简单的得出结果。但是我们显然不可能暴力进......
  • 洛谷 P1099 题解
    洛谷P1099【NOIP2007提高组】树网的核题意简述给定一棵带边权无根树和一个正整数\(s\)。在这棵树的任意直径上截取一段长度不超过\(s\)的路径\(F\),使离\(F\)最远的点到\(F\)的距离最小,求出这个距离。思路记\(\delta(a,b)\)为\(a,b\)之间的路径。对于任意......
  • 省选联考 2024 重塑时光
    首先原问题显然是一个\(\text{DAG}\)计数的形式,施加枚举\(0\)度点集合\(S\)容斥的技巧是自然的。考虑\(k\)刀将其切割成\(t\)段后最终找到一种标号使得存在一种重排方案使其合法的方案数。段内的方案计算是容易的,要求它们所有关系顺序即可,可以快速求出构成一个段的集合......
  • abc344_D - String Bags 题解
    一个月没有碰oi,感觉水平已经退化到负的了。来复健一下。D-StringBagslink题意:给你\(n\)组字符串组,按\(1\)~\(n\)的顺序,对于每组字符串组,可从中至多选一个字符串。求能否用所选串按顺序拼接成指定串,以及选取字符串的最小个数。然后读完题发现是个\(01\)背包;对于第......
  • AT_abc344_e 题解
    本文同步发表于洛谷。赌狗天天输的一集。赛时各种【数据删除】原因导致没做出来。大意给你一个长度为\(N\)的序列\(A=(A_1,\ldots,A_N)\)。保证\(A\)中的元素是不同的。你要处理\(Q\)个操作。每个操作是以下两种类型之一:1xy:在\(A\)中元素\(x\)后面紧接着插入......
  • AT_abc344_d 题解
    赌狗天天输的一集。大意你最开始有一个空字符串\(S\)。你还有编号为\(1,2,\dots,N\)的袋子,每个袋子都包含一些字符串。袋子\(i\)包含\(A_i\)个字符串\(S_{i,1},S_{i,2},\dots,S_{i,A_i}\)。对\(i=1,2,\dots,N\)重复以下步骤仅一次(这里原题没有讲清楚):......