zoukankan      html  css  js  c++  java
  • 【bzoj4822/bzoj1935】[Cqoi2017]老C的任务/[Shoi2007]Tree 园丁的烦恼 树状数组

    原文地址:http://www.cnblogs.com/GXZlegend/p/6825530.html


    bzoj4822

    题目描述

    老 C 是个程序员。    
    最近老 C 从老板那里接到了一个任务——给城市中的手机基站写个管理系统。作为经验丰富的程序员,老 C 轻松地完成了系统的大部分功能,并把其中一个功能交给你来实现。由于一个基站的面积相对于整个城市面积来说非常的小,因此每个的基站都可以看作坐标系中的一个点,其位置可以用坐标(x, y)来表示。此外,每个基站还有很多属性,例如高度、功率等。运营商经常会划定一个区域,并查询区域中所有基站的信息。现在你需要实现的功能就是,对于一个给定的矩形区域,回答该区域中(包括区域边界上的)所有基站的功率总和。如果区域中没有任何基站,则回答 0。

    输入

    第一行两个整数 n, m,表示一共有n个基站和m次查询。    
    接下来一共有 n 行,每行由x_i , y_i , p_i 三个空格隔开的整数构成,表示一个基站的坐标(x_i , y_i )和功率p_i 。不会有两个基站位于同一坐标。    
    接下来一共有m行,每行由x1_j , y1_j , x2_j , y2_j 四个空格隔开的整数构成,表示一次查询的矩形区域。该矩形对角坐标为(x1_j , y1_j )和(x2_j , y2_j ),且 4 边与坐标轴平行。 
    2^31 ≤ x_i , y_i , p_i , x1_j , y1_j , x2_j , y2_j < 2^31, x1_j ≤ x2_j, y1_j ≤ y2_j。   

    输出

    输出 m 行,每行一个整数,对应每次查询的结果。

    样例输入

    4 2
    0 0 1
    0 1 2
    2 2 4
    1 0 8
    0 0 1 1
    1 1 5 6

    样例输出

    11
    4

    bzoj1935

    题目描述

    同上,只是少了个权值p_i,并且y的范围也减小到10^7


    题解

    树状数组

    将点按x递增;将询问拆成2个,离线,离散化,按x递增排序。

    然后每次找到一个询问,就判断有哪些点可以加到树状数组中,然后查询一下就好了。

    注意题目中边上也算是包含,所以应将左下边界-1;同时坐标必须是正的,还需要+2。

    如果是bzoj1935,不需要离散化也可以。

    bzoj4822:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    struct POINT
    {
    	int x , y;
    	ll v;
    }a[500010];
    struct QUERY
    {
    	int p , d , u , id , opt;
    }b[1000010];
    int tot , val[1500010];
    ll f[10000010] , ans[500010];
    bool cmp1(POINT a , POINT b)
    {
        return a.x < b.x;
    }
    bool cmp2(QUERY a , QUERY b)
    {
        return a.p < b.p;
    }
    void update(int x , ll a)
    {
    	int i;
    	for(i = x ; i <= tot ; i += i & -i) f[i] += a;
    }
    ll query(int x)
    {
    	int i;
    	ll ans = 0;
    	for(i = x ; i ; i -= i & -i) ans += f[i];
    	return ans;
    }
    int main()
    {
    	int n , m , i , s = 1;
    	scanf("%d%d" , &n , &m);
    	for(i = 1 ; i <= n ; i ++ ) scanf("%d%d%lld" , &a[i].x , &a[i].y , &a[i].v) , a[i].x += 2 , a[i].y ++ , val[++tot] = a[i].y;
    	for(i = 1 ; i <= m ; i ++ )
    	{
    		scanf("%d%d%d%d" , &b[i].p , &b[i].d , &b[i + m].p , &b[i].u);
    		b[i].p ++ , b[i].d ++ , b[i + m].p += 2 , b[i].u ++ ;
    		b[i + m].d = b[i].d , b[i + m].u = b[i].u;
    		b[i].id = b[i + m].id = i , b[i].opt = -1 , b[i + m].opt = 1;
    		val[++tot] = b[i].d , val[++tot] = b[i].u;
    	}
    	sort(a + 1 , a + n + 1 , cmp1) , sort(b + 1 , b + 2 * m + 1 , cmp2);
    	sort(val + 1 , val + tot + 1);
    	for(i = 1 ; i <= 2 * m ; i ++ )
    	{
    		while(s <= n && a[s].x <= b[i].p) update(lower_bound(val + 1 , val + tot + 1 , a[s].y) - val , a[s].v) , s ++ ;
    		ans[b[i].id] += b[i].opt * (query(lower_bound(val + 1 , val + tot + 1 , b[i].u) - val) - query(lower_bound(val + 1 , val + tot + 1 , b[i].d) - val - 1));
    	}
    	for(i = 1 ; i <= m ; i ++ ) printf("%lld
    " , ans[i]);
    	return 0;
    }
    

    bzoj1935:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    struct POINT
    {
    	int x , y;
    }a[500010];
    struct QUERY
    {
    	int p , d , u , id , opt;
    }b[1000010];
    int f[10000010] , k , ans[500010];
    bool cmp1(POINT a , POINT b)
    {
    	return a.x < b.x;
    }
    bool cmp2(QUERY a , QUERY b)
    {
    	return a.p < b.p;
    }
    void update(int x , int a)
    {
    	int i;
    	for(i = x ; i <= k ; i += i & -i) f[i] += a;
    }
    int query(int x)
    {
    	int i , ans = 0;
    	for(i = x ; i ; i -= i & -i) ans += f[i];
    	return ans;
    }
    int main()
    {
    	int n , m , i , s = 1;
    	scanf("%d%d" , &n , &m);
    	for(i = 1 ; i <= n ; i ++ ) scanf("%d%d" , &a[i].x , &a[i].y) , a[i].x += 2 , a[i].y ++ , k = max(k , a[i].y);
    	for(i = 1 ; i <= m ; i ++ )
    	{
    		scanf("%d%d%d%d" , &b[i].p , &b[i].d , &b[i + m].p , &b[i].u);
    		b[i].p ++ , b[i].d ++ , b[i + m].p += 2 , b[i].u ++ ;
    		b[i + m].d = b[i].d , b[i + m].u = b[i].u , k = max(k , b[i].u);
    		b[i].id = b[i + m].id = i , b[i].opt = -1 , b[i + m].opt = 1;
    	}
    	sort(a + 1 , a + n + 1 , cmp1) , sort(b + 1 , b + 2 * m + 1 , cmp2);
    	for(i = 1 ; i <= 2 * m ; i ++ )
    	{
    		while(s <= n && a[s].x <= b[i].p) update(a[s].y , 1) , s ++ ;
    		ans[b[i].id] += b[i].opt * (query(b[i].u) - query(b[i].d - 1));
    	}
    	for(i = 1 ; i <= m ; i ++ ) printf("%d
    " , ans[i]);
    	return 0;
    }
  • 相关阅读:
    命令
    碎片知识
    驱动问题
    网络基础知识普及
    面向设计大作业——公司餐厅
    面向对象--购物车
    OO之接口-DAO模式代码阅读及应用
    有理数类的定义
    图知识点总结
    Java课程设计总结
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/6825530.html
Copyright © 2011-2022 走看看