zoukankan      html  css  js  c++  java
  • HDU Always Cook Mushroom (极角排序+树状数组)


    Problem Description
    Matt has a company, Always Cook Mushroom (ACM), which produces high-quality mushrooms. 

    ACM has a large field to grow their mushrooms. The field can be considered as a 1000 * 1000 grid where mushrooms are grown in grid points numbered from (1, 1) to (1000, 1000). Because of humidity and sunshine, the productions in different grid points are not the same. Further, the production in the grid points (x, y) is (x + A)(y + B) where A, B are two constant. 

    Matt,the owner of ACM has some queries where he wants to know the sum of the productions in a given scope(include the mushroom growing on the boundary). In each query, the scope Matt asks is a right angled triangle whose apexes are (0, 0), (p, 0), (p, q) 1<=p, q<=1000. 

    As the employee of ACM, can you answer Matt’s queries?

     

    Input
    The first line contains one integer T, indicating the number of test cases.

    For each test case, the first line contains two integers:A, B(0<=A, B<=1000).

    The second line contains one integer M(1<=M<=10^5), denoting the number of queries.

    In the following M lines, the i-th line contains three integers a, b, x (1<=a, b<=10^6, 1<=x<=1000), denoting one apex of the given right angled triangle is (x, 0) and the slope of its base is (a, b). It is guaranteed that the gird points in the given right angled triangle are all in valid area, numbered from (1, 1) to (1000, 1000).
     

    Output
    For each test case, output M + 1 lines.

    The first line contains "Case #x:", where x is the case number (starting from 1) 

    In the following M lines, the i-th line contains one integer, denoting the answer of the i-th query.
     

    Sample Input
    2 0 0 3 3 5 8 2 4 7 1 2 3 1 2 3 3 5 8 2 4 7 1 2 3
     

    Sample Output
    Case #1: 1842 1708 86 Case #2: 2901 2688 200
     

    Source

    题意:给定一个1000x1000的点阵。m组询问。每次询问一个由(0,0)、(x,0)点一以及从原点出发的方向向量(a,b)构成的直角三角形包围的点的权值和。

    思路: 预处理出这1e6个点的极角关系序,离线。将询问也按(a,b)的极角排序。然后只需想象一根表针在逆时针的扫。把扫过的点的权值加到树状数组中,对于每个询问也不过一个前缀和。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    typedef long long ll;
    using namespace std;
    const int maxn = 1005;
    const int inf = 1e5+5;
    
    struct Point {
    	ll a, b;
    	double s;
    } p[maxn*maxn];
    struct Query {
    	ll a, b, x, id;
    	double s;
    } q[maxn*maxn];
    ll bit[maxn];
    ll ans[inf], Index[inf];
    int cnt;
    
    void scan(ll &x) {
    	char c;
    	while ((c = getchar()) && (c < '0' || c > '9')) ;
    	x = c - '0';
    	while ((c = getchar()) && (c >= '0' && c <= '9'))
    		x = x * 10 + c - '0';
    }
    
    void out(ll x) {
    	if (x > 9)
    		out(x/10);
    	putchar(x%10+'0');
    }
    
    inline int lowbit(int x) {
    	return x & -x;
    }
    
    inline void add(int x, int val) {
    	while (x <= 1000) {
    		bit[x] += val;
    		x += lowbit(x);
    	}
    }
    
    inline ll sum(int x) {
    	ll tmp = 0;
    	while (x > 0) {
    		tmp += bit[x];
    		x -= lowbit(x);
    	}
    	return tmp;
    }
    
    bool cmp1(Point x, Point y) {
    	return x.s < y.s;
    }
    
    bool cmp2(Query x, Query y) {
    	if (x.s == y.s)
    		return x.x < y.x;
    	return x.s < y.s;
    }
    
    void init() {
    	for (int i = 1; i <= 1000; i++)
    		for (int j = 1; j <= 1000; j++) {
    			p[cnt].a = i;
    			p[cnt].b = j;
    			p[cnt++].s = 1.0 * j / i;
    		}
    	sort(p, p+cnt, cmp1);
    }
    
    int main() {
    	cnt = 0;
    	ll A, B, m;
    	init();
    	int t, cas = 1;
    	scanf("%d", &t);
    	while (t--) {
    		memset(bit, 0, sizeof(bit));
    		scan(A), scan(B), scan(m);
    		for (int i = 0; i < m; i++) {
    			scan(q[i].a), scan(q[i].b), scan(q[i].x);
    			q[i].s = 1.0 * q[i].b / q[i].a;
    			q[i].id = i;
    		}
    
    		sort(q, q + m, cmp2);
    		for (int i = 0; i < m; i++) {
    			Index[q[i].id] = i;
    		}
    		cnt = 0;
    		printf("Case #%d:
    ", cas++);
    		for (int i = 0; i < m; i++) {
    			while (p[cnt].s <= q[i].s) {
    				add(p[cnt].a, (p[cnt].a+A) * (p[cnt].b + B));
    				cnt++;
    			}
    			ans[i] = sum(q[i].x);
    		}
    		for (int i = 0; i < m; i++) {
    			out(ans[Index[i]]);
    			printf("
    ");
    		}
    	}
    	return 0;	
    }





  • 相关阅读:
    获取资源文件 r.drawable中的图片转换为drawable、bitmap
    Android 启动白屏或者黑屏闪现解决
    Android应用截图方法
    史上最全的变量、作用域和内存问题
    RunLoop总结:RunLoop的应用场景(四)
    poj3436 ACM Computer Factory, 最大流,输出路径
    android开发——从相冊中选择图片不裁剪
    <html>
    poj3073
    poj 2482 Stars in Your Window (线段树扫描线)
  • 原文地址:https://www.cnblogs.com/yxysuanfa/p/6724238.html
Copyright © 2011-2022 走看看