【OJ2216】小奇的數列
阿新 • • 發佈:2018-08-02
找到 space tchar 抽屜原理 ext for != ace spa 為 \(0\) ,可以據此讓區間大小大於 \(P\) 的區間直接輸出 \(0\) 。
2216 -- 小奇的數列(Solution)
題目大意 : 給定一個長度為?\(n\)?的數列,以及?\(m\)?次詢問,每次給出三個數?\(l\),\(r\)?和?\(P\),詢問 \((\sum_{i=l_1}^{r_1}a_i)\;mod\;P\)?的最小值。 其中 \(l \le l_1 \le r_1 \le r\) 。 \((n\le 5\times 10^5, m\le 10^4,P\le 500)\)
Tag: 抽屜原理、STL
Analysis By LC:
最樸素的做法當然是計算前綴和再枚舉 \(l_1\) 和 \(r_1\) 。這裏有一個優化:如果區間中有超過 \(P\) 個元素,那麽可以根據抽屜原理證明一定存在一個區間使得區間和膜 \(P\)
那麽我們只考慮枚舉 \(l_1\) 和 \(r_1\) 中的一個是否可以完成本題?我們可以只枚舉 \(r_1\) ,顯然我們要找到一個 \(l_1\) ,使得 \(s[r_1]-s[l_1]\) 最小,即 \(s[l_1]\) 與 \(s[r_1]\) 最接近,用STL的 \(\text Set\) 即可維護。(這裏 \(s[x]\) 表示 \((sum[x]-sum[l-1])\,mod\,P\) )
Code By LC :
#include<cstdio> #include<algorithm> #include<set> using namespace std; inline int _read() { char c; int x=0; for(;c<'0'||c>'9';c=getchar()); for(;c>='0'&&c<='9';c=getchar())x=(x<<1)+(x<<3)+c-'0'; return x; } typedef long long ll; const int N=500005; int a[N]; ll sum[N]; int main() { int n=_read(),m=_read(); for(int i=1;i<=n;i++) { a[i]=_read(); sum[i]=sum[i-1]+a[i]; } while(m--) { int l=_read(),r=_read(),p=_read(),ans=501; set<ll> s; s.insert(0); if(r-l+1>=p) { puts("0"); continue; } for(int i=l;i<=r;i++) { ll w=(sum[i]-sum[l-1])%p; auto it=s.upper_bound(w); if(it!=s.begin())--it; ans=min(ans,int((w-*it)%p)); s.insert(w); } printf("%d\n",ans); } }
【OJ2216】小奇的數列