把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

CF889E Mod Mod Mod

题面传送门

看到这题的第一眼想法:哇这不是从\(n\)倒过来维护一些区间的右端点每次增加\(O(1)\)个区间,平移若干区间,得到\(O(n)\)个取值点,然后对于每个点二分出第一个能模的位置,暴力做得到\(O(n\log n\log A)\)的优秀复杂度吗?

哎等下,这东西好像要写个平衡树写个st表有点难写的亚子?

然后你发现他们写的都是不到1k的东西,因此肯定不用这么麻烦。

我们考虑正着维护,到了第\(i\)个数模完之后,考虑维护一整段的答案,如果当前的是\([0,x]\),则每个点拥有共同的初始值\(b\)与斜率\(i\),点则是他们自己。那么一定是取\(x\)最优。

然后这时候\(\bmod a_i\),则模完之后有效的是两段:\([0,a_i-1]\)\([0,x\bmod a_i]\),新拆出来的段的初始值只需要加上询问点变化的差即可。容易发现这样每个数会模\(O(\log A)\)次,用map存状态,总复杂度\(O(n\log n\log A)\)

code:

#include<bits/stdc++.h>
#define I inline
#define ll long long
#define db double
#define lb long db
#define N (200000+5)
#define M ((N<<1)+5)
#define K (700+5)
#define mod 1000000007
#define Mod (mod-1)
#define eps (1e-5)
#define ull unsigned ll
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((k+1)*(x)+(y))
#define R(n) (1ll*rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using namespace std;const ll INF=1e18;map<ll,ll> f;
int n,m,k;ll x,ToT;
int main(){
	freopen("1.in","r",stdin);
	int i,j;scanf("%d%lld",&n,&x);f[x-1]=0;for(i=2;i<=n;i++){
		scanf("%lld",&x);ll Ts=-1e18;while(!f.empty()){
			auto j=*--f.end();if(j.first<x){Ts>=0&&(f[x-1]=max(f[x-1],Ts));break;}Ts=max(j.second+(i-1)*(j.first/x*x-x),Ts);
			f[j.first%x]=max(f[j.first%x],j.second+(j.first-j.first%x)*(i-1));f.erase(--f.end());
		} 
	} for(auto i:f) ToT=max(ToT,i.second+i.first*n);printf("%lld\n",ToT);
} 
posted @ 2022-08-06 21:10  275307894a  阅读(36)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end