AtCoder Regular Contest 068E:Snuke Line
阿新 • • 發佈:2018-12-23
題目傳送門:https://arc068.contest.atcoder.jp/tasks/arc068_c
題目翻譯
直線上有\(0~m\)這\(m+1\)個點,一共有\(m\)輛火車。第\(i\)輛火車只會在\(i\)的倍數點上停靠,所有車都從\(0\)號點出發。
一共有\(n\)個商品,第\(i\)個商品只會在\(l_i~r_i\)號點出售,問你對於每輛火車,在可以停靠的站裡,可以買到的商品種類數。
\(m\leqslant 10^5,n\leqslant 3*10^5\)。
題解
對於長度大於等於\(i\)的區間,肯定會對\(i\)號火車有貢獻。長度小於\(i\)的,我們用樹狀陣列差分查詢就行了。
因為所有站點總和為\(mlogm\),所以時間複雜度為\(mlog^2m\)。
時間複雜度: \(O(mlog^2m)\)
空間複雜度:\(O(m)\)
程式碼如下:
#include <cstdio> #include <vector> using namespace std; #define low(i) ((i)&(-(i))) const int maxm=1e5+5; int n,m,cnt; vector<int>range[maxm]; vector<int>::iterator it; int read() { int x=0,f=1;char ch=getchar(); for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1; for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0'; return x*f; } struct TreeArray { int c[maxm]; void change(int pos,int v) { for(int i=pos;i<=m;i+=low(i)) c[i]+=v; } int query(int pos) { int res=0; for(int i=pos;i;i-=low(i)) res+=c[i]; return res; } }T; int main() { cnt=n=read(),m=read(); for(int i=1;i<=n;i++) { int l=read(),r=read(); range[r-l+1].push_back(l); } for(int i=1;i<=m;i++) { int ans=cnt; for(int pos=i;pos<=m;pos+=i) ans+=T.query(pos); for(it=range[i].begin();it!=range[i].end();it++) T.change(*it,1),T.change((*it)+i,-1),cnt--; printf("%d\n",ans); } return 0; }