1 条题解
-
1yejun LV 10 MOD @ 2019-06-01 11:35:47
这道题目本来挺难的,但是由于周四晚上的讨论会提到了这道题目,所以就把它放到了第一题。在看提交的时候,发现这题貌似不用单调队列,只要维护前缀和的最小值,然后在环上O(1)转移即可。
贴上我又臭又长的单调队列代码写法。#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<set> #include<map> #include<queue> #include<stack> #include<vector> #include<cstring> #include<cstdlib> using namespace std; typedef long long ll; const int maxn=500000+5; const ll INF=0x3f3f3f3f3f3f3f3fll; int n,l; int s[maxn],d[maxn],q[maxn*2]; int sum[maxn*2],que[maxn*2]; //sum单调递减的序列 bool f[maxn]; void init() { int tail=0,head=1; for(int i=1; i<n; i++) { while(head<=tail&&sum[que[tail]]>=sum[i]) tail--; que[++tail]=i; } // for(int i=1;i<=tail;i++){ // cout<<que[tail]<<" "; // } // cout<<endl; for(int i=n; i<=2*n; i++) { while(head<=tail&&i-que[head]>2*n) head++; while(head<=tail&&sum[que[tail]]>=sum[i]) tail--; que[++tail]=i; if(sum[i]-sum[que[head]]==0) { // cout<<i<<endl; f[i-n+1]=true; } } } int main() { ios::sync_with_stdio(false); //freopen("环城旅行.in","r",stdin); memset(f,0,sizeof(f)); // cout<<!0<<endl; cin>>n>>l; int sum1=0; for(int i=1; i<=n; i++) { cin>>d[i]>>s[i]; //距离 加油量 sum1+=d[i]; } d[n+1]=l-sum1; int top1=0,top2=1; for(int i=1; i<=n; i++) { q[i]=s[i]-d[i+1]; } // cout<<top1<<" "<<top2<<endl; for(int i=n+1; i<=2*n; i++) { q[i]=q[i-n]; } for(int i=1; i<=2*n; i++) { sum[i]=sum[i-1]+q[i]; } // for(int i=1;i<=4*n;i++){ // cout<<sum[i]<<" "; // } // cout<<endl; init(); bool flag=false; for(int i=1; i<=n; i++) { if(f[i]) { cout<<i<<" "; flag=true; } } if(!flag) cout<<-1; return 0; }
然后是不用单调队列的写法。(来自nnu19170323的提交)
#include <iostream> using namespace std; const int MAXN=500005; int n,L; int d,s; int sum[MAXN]; int Min=0x7fffffff; int main() { cin>>n>>L; if(n==1) { cout<<1<<endl; return 0; } cin>>d; for(int i=2;i<=n;i++) { cin>>s>>d; sum[i]=sum[i-1]+s-d; if(sum[i]<Min) Min=sum[i]; } cin >> s; for(int i=1;i<=n;i++) if(sum[i]==Min) cout<<i<<" "; return 0; }
- 1