Codeforces Round #510 (Div. 2) D. Petya and Array (樹狀陣列)
阿新 • • 發佈:2018-12-13
題意:求所有區間和小於的這樣的區間數量。
思路:從 到的和小於,即,其中是的字首和。實現的方法就是從前往後對於每一個,看在它前面有多少個大於的字首和。
這個過程用樹狀陣列來維護,每次加入,然後查詢。這樣可以保證每次查詢的時候,存在於樹狀陣列中的必然是在i之前的字首和。
#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 2e5 + 5;
const int mod = 1e9 + 7;
int lowbit(int x) {
return x & -x;
}
ll n, t;
ll bit[maxn];
ll a[maxn], b[maxn];
void add(ll i, ll x) {//第i個位置+x
while (i <= (n + 1)) { //有n+1個字首和數字
bit[i] += x;
i += lowbit(i);
}
}
ll query(ll x) {
ll ans = 0;
while (x) {
ans += bit[x];
x -= lowbit(x);
}
return ans;
}
int main() {
scanf("%lld%lld", &n, &t);
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
a[i] += a[i - 1];
b[i] = a[i];
}
sort(b, b + 1 + n);//這樣子是為了存b[0]=0;
ll cnt = 0;
int pos;
for (int i = 1; i <= n; i++) {
pos = lower_bound(b, b + 1 + n, a[i - 1]) - b + 1;
//不加1的話從0開始,樹狀陣列的下標從1開始
add(pos, 1);
// pos = upper_bound(b, b + n + 1, a[i] - t ) - b ;//這個也行
pos = lower_bound(b, b + n + 1, a[i] - t + 1) - b;
/*
因為是sum[i-1]>sum[j]-t,是大於號
所以要麼low_bound裡面加1,要麼upper_bound
*/
cnt += i - query(pos);
}
printf("%lld\n", cnt);
return 0;
}