E. Ina of the Mountain 数据结构 优先队列
题意:给你一个长度为n的序列。问你最少进行多少次操作,使得最终整个序列的值都为k
操作:选一段区间,然后把这段区间的数全减一。
这个序列还有一个特性,就是当一个数为0时,这个数会变成k。
解法:一眼丁真P1969 [NOIP2013 提高组] 积木大赛 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn),但这个没那么简单。
首先也是从上面这道橙题考虑,这道橙题的做法就是贪心,然后对于每一个相邻的两项且后项大于前项的,ans加上其差值就好了。
这个样子贪心是对的,因为我们选择一个区间,当我们去减这个区间最大的数的时候,小的数也跟着就剪完了。
然后我们想想这道题与上题的不同之处,那就是当我们还可以去把一个数减到0后再继续减,那样他就又变成一个大数了。所以当后项大于前项我们依然取差值,但反之我们就让后项加k再减前项。这是没有问题的。
所以当我们遇到前项大于后项时,可以考虑把黑色变成红色,然后就可以省掉下一次的后项大于前项的差了。
同理,当前面有前项小于后项且我们没有用过,也可以如上图变,当然我这个画的不标准,花了波浪线那里的意思是他是很曲折的。
然后我们开一个堆来维护前面的最小值,就可以a掉了
#include<bits/stdc++.h> #define de cout<<111<<"\n"; #define fi first #define se second #define ll long long #define kx(a,b) ((a*b)%mod) #define kplus(a,b) ((a+b)%mod) #define lowbit(x) x&(-x); #define up(a,b) ((a-1ll)/b+1ll) typedef __int128 Int; using namespace std; const int N=1000010; const ll mod=998244353; //const int mod=1000000007; typedef pair<int,int> pii; ll fect[N], infect[N]; ll binpow(ll a,ll b,ll c){ ll ans=1; while(b){ if(b&1) ans=(Int)ans*a%c; a=(Int)a*a%c; b>>=1; } return ans;} int C(int a,int b){ return fect[a]*infect[b]%mod*infect[a-b]%mod;} void initzuhe(int n){ fect[0]=1;infect[0]=1; for(int i=1;i<=n;i++){ fect[i]=(fect[i-1]*i)%mod; } infect[n-1]=binpow(fect[n-1],mod-2ll,mod); for(int i=n-2;i>=1;i--) infect[i]=infect[i+1]*(i+1ll)%mod;} ll test[12]={2,3,5,7,11,13,17,19,23,29,31,37},maxn; bool check(ll a,ll n){ ll d=n-1,get=binpow(a,d,n); if(get!=1) return 1; while((d&1)^1) if(d>>=1,(get=binpow(a,d,n))==n-1) return 0; else if(get!=1) return 1; return 0;} bool miller_rabbin(ll n) { if(n<40){ for(int i=0;i<12;i++) if(test[i]==n) return 1; return 0; } for(int i=0;i<12;i++) if(check(test[i],n)) return 0; return 1;} ll gcd(ll a,ll b){ return !b?a:gcd(b,a%b);} inline ll f(ll x,ll c,ll n){ return ((Int)x*x+c)%n;} ll pollard_rho(ll x){ ll s=0,t=0,c=1ll*rand()%(x-1)+1,val=1; for(int i=1;;i<<=1,s=t,val=1){ for(int j=1;j<=i;j++){ t=f(t,c,x); val=(Int)val*abs(t-s)%x; if(!(j%127)){ ll d=gcd(val,x); if(d>1) return d; } } ll d=gcd(val,x); if(d>1) return d; }} ll x,y; ll exgcd(ll a,ll b,ll &x,ll &y){ if(b==0){ x=1ll,y=0ll; return a; } ll temp=exgcd(b,a%b,x,y); ll z=x;x=y; y=z-a/b*y; return temp; } void solve(){ int n,k;cin>>n>>k;priority_queue<int,vector<int>,greater<int>>a; int pre=0; ll ans=0ll; for(int i=1;i<=n;i++){ int c;cin>>c;c%=k; if(c>=pre){ a.push(c-pre); ans+=a.top(); a.pop(); } else{ a.push(k+c-pre); } pre=c; } cout<<ans<<"\n"; } signed main(){ std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); srand((unsigned)time(NULL)); int t;cin>>t;while(t--) solve(); }
本文作者:magic_night
本文链接:https://www.cnblogs.com/shi5/p/17675665.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步