zoukankan      html  css  js  c++  java
  • BZOJ4627: [BeiJing2016]回转寿司

    这题调了一晚上快调死了= = 

    此题看着很奇怪,我们先搞一搞式子看看它到底要我们求什么

    大概是 ∑ni=1 [L <= Σkj=i a_i <= R] (k >= i)

    发现这可以转成前缀和的形式

    就是 ∑ni=1 [L <= s[k] - s[j] <= R] (i <= j <= k)

    发现它就是求对于每一个 s[k] 满足 s[j] ∈ [s[k] - R, s[k] - L] 的 s[j] 个数

    可以权值线段树区间求和搞啊!

    然后就是一个裸的线段树了

    二分和离散化总容易出一些奇怪的小锅


    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<cstdio>
    #define lson (x << 1)
    #define rson ((x << 1) | 1)
    using namespace std;
    
    typedef long long ll;
    const int MAXN = 100005;
    
    struct Node{
    	ll sum;
    }t[(MAXN * 3) << 2];
    int n, sizb, rnk[MAXN];
    ll lll, rrr, res;
    ll num[MAXN], uni[MAXN * 3];
    
    inline void pushup(int x) {
    	t[x].sum = t[lson].sum + t[rson].sum;
    	return;
    }
    void update(int dst, int l, int r, int x) {
    	if(l == r) {
    		++t[x].sum;
    		return;
    	}
    	int mid = ((l + r) >> 1);
    	if(dst <= mid) update(dst, l, mid, lson);
    	else update(dst, mid + 1, r, rson);
    	pushup(x);
    	return;
    }
    ll query(int L, int R, int l, int r, int x) {
    	if(L > R) return 0ll;
    	if(L <= l && r <= R) {
    		return t[x].sum;
    	}
    	int mid = ((l + r) >> 1);
    	ll ans = 0ll;
    	if(L <= mid) ans = query(L, R, l, mid, lson);
    	if(mid < R) ans += query(L, R, mid + 1, r, rson);
    	return ans;
    }
    inline int lower(int l, int r, ll val, ll *arr) {
    	register int mid;
    	while(l < r) {
    		mid = ((l + r) >> 1);
    		if(arr[mid] >= val) r = mid;
    		else l = mid + 1;
    	}
    	return l;
    }
    inline int upper(int l, int r, ll val, ll *arr) {
    	register int mid;
    	while(l < r) {
    		mid = ((l + r + 1) >> 1);
    		if(arr[mid] <= val) l = mid;
    		else r = mid - 1;
    	}
    	return l;
    }
    
    int main() {
    	scanf("%d%lld%lld", &n, &lll, &rrr);
    	uni[++sizb] = 0ll;
    	register ll pres = 0ll;
    	for(int i = 1; i <= n; ++i) {
    		scanf("%lld", &num[i]);
    		pres += num[i];
    		uni[++sizb] =  pres;
    		uni[++sizb] = pres - rrr;
    		uni[++sizb] = pres - lll;
    	}
    	sort(uni + 1, uni + sizb + 1);
    	sizb = unique(uni + 1, uni + sizb + 1) - uni - 1;
    	pres = 0ll;
    	for(int i = 1; i <= n; ++i) {
    		pres += num[i];
    		rnk[i] = lower_bound(uni + 1, uni + sizb + 1, pres) - uni;
    	}
    	update(lower_bound(uni + 1, uni + sizb + 1, 0) - uni, 1, sizb, 1);
    	pres = 0ll;
    	for(int i = 1; i <= n; ++i) {
    		pres += num[i];
    		int lef = lower(1, sizb, pres - rrr, uni), rig = upper(1, sizb, pres - lll, uni);
    		res += query(lef, rig, 1, sizb, 1);
    		update(rnk[i], 1, sizb, 1);
    	}
    	printf("%lld
    ", res);
    	return 0;
    }
    

      

    禁止诸如开发者知识库/布布扣/码迷/学步园/马开东等 copy 他人博文乃至博客的网站转载 ,用户转载请注明出处:https://www.cnblogs.com/xcysblog/
  • 相关阅读:
    springboot ssm propertis 如何搭建多数据源动态切换
    发送验证码
    二维码生成
    文件上传 下载
    git拉代码报错
    通过url 下载文件
    原生JS实现挡板小球游戏
    深入浅出解析AJAX
    深入解析CSS3圆周运动
    JS递归原理
  • 原文地址:https://www.cnblogs.com/xcysblog/p/9617141.html
Copyright © 2011-2022 走看看