Bzoj4627: [BeiJing2016]回转寿司

来源:互联网 发布:单片机恒温控制系统 编辑:程序博客网 时间:2024/04/19 14:39

原题网址:http://www.lydsy.com/JudgeOnline/problem.php?id=4627
考虑先将从第一项开始的所有子串和求出来,找符合条件的[L,R]的子串和个数,然后把这些都减去第一项,就是从第二项开始的所有子串和,实际上不用真的减,只要在L,R上加即可。用树状数组维护一个子串和区间内存在的子串和个数,每次找L~R中的即可。

#include<bits/stdc++.h>typedef long long ll;const int N = 1e5 + 10;const ll INF = 1e18;template <typename T> void read(T &x){    x = 0; T f = 1;    char c = getchar();    while (c < '0' || c > '9') {if (c == '-') f *= -1; c = getchar();}    while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}    x *= f;}int n,a[N],tr[N],pos[N];ll L,R,ans;struct rec{ll s; int num;} b[N];bool cmp(const rec &a, const rec &b){    return a.s < b.s;}void add(int x, int f){    for (; x<=n; x+=x&-x)        tr[x] += f;}int qry(int x){    int ans = 0;    for (; x>0; x-=x&-x)        ans += tr[x];    return ans;}int main(){    read(n);read(L);read(R);    for (int i=1; i<=n; i++) read(a[i]);    for (int i=1; i<=n; i++) b[i] = (rec) {b[i-1].s+a[i],i};    std::sort(b+1,b+n+1,cmp);    for (int i=1; i<=n; i++) pos[b[i].num] = i;    b[0].s = -INF, b[n+1].s = INF;    for (int i=1; i<=n; i++) add(i,1);    int l,r,mid;    for (int i=1; i<=n; i++){        l = 0, r = n+1;        while (l<r){            mid = (l+r)/2;            if (b[mid].s>=L)                r = mid;            else                l = mid + 1;        }        ans -= qry(l - 1);        l = 0, r = n+1;        while (l<r){            mid = (l+r+1)/2;            if (b[mid].s<=R)                l = mid;            else                r = mid - 1;        }        ans += qry(l);        add(pos[i],-1);        L += a[i], R += a[i];    }    printf("%lld\n",ans);    return 0;} 
0 0