首页 > 其他分享 >[省选联考 2024] 季风 题解

[省选联考 2024] 季风 题解

时间:2024-03-10 17:27:09浏览次数:24  
标签:__ p2 p1 省选 题解 ll read int128 联考

\(\large\textbf{Statement.}\)

求出最小的非负整数 \(m\),使得:

\[\left|x-\sum_{i=0}^{m-1} x_{i \bmod n}\right|+\left|y-\sum_{i=0}^{m-1} y_{i \bmod n}\right|\le mk \]


\(\large\textbf{Solution.}\)

考虑枚举 \(m \bmod n\),然后求和就转化成了一段前缀和加上整个序列和的若干倍。

发现左边的式子是个下凸函数,而且是由三段线性函数组成的。只有在某对绝对值符号内的东西符号改变时斜率才会改变,可以求出改变时的横坐标,然后三段函数分别考虑。

对于一段函数,要求出线段上最靠左且在直线 \(y=nkx+ik\) 下方的点。

先判掉最左边的点满足条件和在不满足该情况下最右边的点不满足条件的情况,前者已经找到了最靠左的那个点,后者无解。

然后对于剩下的情况一定存在一个交点,求出交点的坐标然后就做完了。

时间复杂度 \(\mathcal O(n)\)。注意有多处要用到 __int128,另外如果直接调用 abs(__int128) 无法通过编译。

参考代码:

#include<bits/stdc++.h>
#define ll long long
#define mxn 100003
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
inline int read(){
    int x=0;bool fl=0;char c=getchar();
    while(!isdigit(c)){if(c=='-')fl=1;c=getchar();}
    while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return fl?-x:x;
}
int t,n,k,x,y,a[mxn],b[mxn];
ll ans,ps,s1[mxn],s2[mxn];
inline __int128 abs(__int128 x){
    return x<0?-x:x;
}
inline __int128 get(int i,ll j){
    return abs(s1[i]+(__int128)s1[n]*j-x)+abs(s2[i]+(__int128)s2[n]*j-y);
}
void solve(int i,ll l,ll r){
	if(l>r)return;
	if(get(i,l)<=(i+(__int128)n*l)*k){
		ans=min((__int128)ans,(__int128)l*n+i);
		return;
	}
	if(get(i,r)>(i+(__int128)n*r)*k)return;
	__int128 y1=get(i,l),y2=get(i,r),k1=(ll)n*k-(y2-y1)/(r-l);
	ll ps=(get(i,l)-(i+(__int128)n*l)*k+k1-1)/k1+l;
	ans=min((__int128)ans,(__int128)ps*n+i);
}
signed main(){
    t=read();
    while(t--){
        n=read(),k=read(),x=read(),y=read();
        rep(i,1,n){
            a[i]=read(),b[i]=read();
            s1[i]=s1[i-1]+a[i],s2[i]=s2[i-1]+b[i];
        }
        if(!x&&!y){
            puts("0");
            continue;
        }
        ans=5e18;
        rep(i,0,n){
        	ll p1=max(s1[n]?(x-s1[i])/s1[n]:(ll)1e16,0ll),p2=max(s2[n]?(y-s2[i])/s2[n]:(ll)1e16,0ll);
        	if(p1>p2)swap(p1,p2);
        	solve(i,0,p1);
        	solve(i,p1+1,p2);
        	solve(i,p2+1,1e16);
        }
        if(ans==5e18)puts("-1");
        else printf("%lld\n",ans);
    }
    return 0;
}

标签:__,p2,p1,省选,题解,ll,read,int128,联考
From: https://www.cnblogs.com/zifanoi/p/18064409

相关文章

  • 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\)重复以下步骤仅一次(这里原题没有讲清楚):......
  • P10238 [yLCPC2024] F. PANDORA PARADOXXX 题解
    分析考虑时光倒流。对于需要合并的两个连通块\(x,y\),其合并之后的最远点对距离一定是合并之前的两组点对中产生的。在合并的时候枚举点对,取距离最大值即可。由于我们是倒着来的,所有连通块的最远点对距离最大值不减,所以能直接在合并之后取最大值。维护连通块用并查集即可。复杂......