ARC068C - Snuke Line
ARC068C - Snuke Line
Description
其實就是給出nnn個區間[li,ri][l_i,r_i][li?,ri?]對于每一個i∈[1,M]i\in[1,M]i∈[1,M],求:
∑j=1n[?rji???lj?1i?≥1]\sum_{j=1}^n[\lfloor \frac{r_j}{i}\rfloor-\lfloor \frac{l_j-1}{i}\rfloor\geq 1]j=1∑n?[?irj?????ilj??1??≥1]
好吧其實這樣思考感覺更難了。。。
Solution
考慮計算這個的瓶頸,我們自然地想到用調和級數級別的方法去計算這類問題:對于每個位置ttt,求出st=∑jt∈[lj,rj]s_t=\sum_j{t\in[l_j,r_j]}st?=∑j?t∈[lj?,rj?],也就是ttt被包含的區間個數(這可以用樹狀數組維護),然后直接枚舉iii的倍數計算答案。但這樣會有問題,原因在于一個區間可能存在多個iii的倍數,產生重復貢獻。
進一步的,我們發現當rj?lj+1>=ir_j-l_j+1>=irj??lj?+1>=i時,必然為111,否則必然不大于111,有了這個性質,我們就可以只對長度小于iii的區間統計sis_isi?,枚舉iii的倍數計算,剩下的區間都會產生111的貢獻,直接統計即可。
時間復雜度O(nlnMlgM+nlgn)O(n\;lnM\;lgM+nlgn)O(nlnMlgM+nlgn)。
Code
#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cctype> #include <string> #include <cstring> #include <ctime> #include <cassert> #include <string.h> //#include <unordered_set> //#include <unordered_map> //#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B) #define PB(A) push_back(A) #define SIZE(A) ((int)A.size()) #define LEN(A) ((int)A.length()) #define FOR(i,a,b) for(int i=(a);i<(b);++i) #define fi first #define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; } template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll; typedef unsigned long long ull; typedef long double lod; typedef pair<int,int> PR; typedef vector<int> VI;const lod eps=1e-11; const lod pi=acos(-1); const int oo=1<<30; const ll loo=1ll<<62; const int mods=998244353; const int MAXN=300005; const int INF=0x3f3f3f3f;//1061109567 /*--------------------------------------------------------------------*/ inline int read() {int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f; } PR a[MAXN]; int s[MAXN],n,m; void add(int x,int y) { for (;x<=m+1;x+=x&(-x)) s[x]+=y; } int query(int x) { int ans=0; for (;x;x-=x&(-x)) ans+=s[x]; return ans; } signed main() {n=read(),m=read();for (int i=1;i<=n;i++) a[i].fi=read(),a[i].se=read();sort(a+1,a+n+1,[&](PR x,PR y){ return x.se-x.fi<y.se-y.fi; });for (int i=1,nw=1;i<=m;i++){while (nw<=n&&a[nw].se-a[nw].fi+1<i) add(a[nw].fi,1),add(a[nw].se+1,-1),nw++;int ans=n-nw+1;for (int j=i;j<=m;j+=i) ans+=query(j);printf("%d\n",ans);}return 0; }總結
以上是生活随笔為你收集整理的ARC068C - Snuke Line的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FLT语法(转)
- 下一篇: [ARC072C]Alice in li