[BJOI2016] 回轉壽司
阿新 • • 發佈:2022-04-06
前言
不是很懂,這題在洛谷上竟然是紫的。
題目
講解
很多做法啊,離散化樹狀陣列,主席樹,cdq 都行,我這裡是常數較小的 cdq 做法。
是在沒啥好講的,做個字首和,直接 cdq分治 + two-pointer 就做完了,注意邊界問題。
用歸併排序減小 cdq 常數是常見做法。
程式碼
寫醜了。
//12252024832524 #include <bits/stdc++.h> #define TT template<typename T> using namespace std; typedef long long LL; const int MAXN = 100005; int n,L,R; LL pre[MAXN],ans; LL Read() { LL x = 0,f = 1;char c = getchar(); while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();} return x * f; } TT void Put1(T x) { if(x > 9) Put1(x/10); putchar(x%10^48); } TT void Put(T x,char c = -1) { if(x < 0) putchar('-'),x = -x; Put1(x); if(c >= 0) putchar(c); } TT T Max(T x,T y){return x > y ? x : y;} TT T Min(T x,T y){return x < y ? x : y;} TT T Abs(T x){return x < 0 ? -x : x;} LL tmp[MAXN]; void cdq(int l,int r){ if(l == r) return; int mid = (l+r) >> 1,ql = l,qr = l-1; cdq(l,mid); cdq(mid+1,r); for(int i = mid+1;i <= r;++ i){ while(ql < mid && pre[i] - pre[ql] > R) ++ql; while(qr < mid && pre[i] - pre[qr+1] >= L) ++qr; if(ql <= mid && qr <= mid && pre[i] - pre[ql] <= R && pre[i] - pre[qr] >= L) ans += qr-ql+1; } int i = l,j = mid+1,k = l; while(i <= mid && j <= r){ if(pre[i] <= pre[j]) tmp[k++] = pre[i++]; else tmp[k++] = pre[j++]; } while(i <= mid) tmp[k++] = pre[i++]; while(j <= r) tmp[k++] = pre[j++]; for(int p = l;p <= r;++ p) pre[p] = tmp[p]; } int main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); n = Read(); L = Read(); R = Read(); for(int i = 1;i <= n;++ i) pre[i] = pre[i-1] + Read(); cdq(0,n); Put(ans,'\n'); return 0; }