zoukankan      html  css  js  c++  java
  • [BZOJ2850]巧克力王国

    [BZOJ2850]巧克力王国

    试题描述

    巧克力王国里的巧克力都是由牛奶和可可做成的。但是并不是每一块巧克力都受王国人民的欢迎,因为大家都不喜
    欢过于甜的巧克力。对于每一块巧克力,我们设x和y为其牛奶和可可的含量。由于每个人对于甜的程度都有自己的
    评判标准,所以每个人都有两个参数a和b,分别为他自己为牛奶和可可定义的权重,因此牛奶和可可含量分别为x
    和y的巧克力对于他的甜味程度即为ax + by。而每个人又有一个甜味限度c,所有甜味程度大于等于c的巧克力他都
    无法接受。每块巧克力都有一个美味值h。现在我们想知道对于每个人,他所能接受的巧克力的美味值之和为多少

    输入

    第一行两个正整数n和m,分别表示巧克力个数和询问个数。接下来n行,每行三个整数x,y,h,含义如题目所示。再
    接下来m行,每行三个整数a,b,c,含义如题目所示。

    输出

    输出m行,其中第i行表示第i个人所能接受的巧克力的美味值之和。

    输入示例

    3 3
    1 2 5
    3 1 4
    2 2 1
    2 1 6
    1 3 5
    1 3 7

    输出示例

    5
    0
    4

    数据规模及约定

    1 <= n, m <= 50000,1 <= 10^9,-10^9 <= a, b, x, y <= 10^9。

    题解

    题意就是统计一条给定直线下方或是上方的点权和。讨论一下 a 和 b 的正负性,然后判断一下一个矩形内是否可能有合法的点。

    例如斜率为正的一条直线和一个矩形,要统计直线上方的点。若矩形左上角在直线上方则这个矩形可能有合法的点,若矩形右下角在直线上方则这个矩形内所有点都合法。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <map>
    #include <set>
    using namespace std;
    #define LL long long
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
        if(Head == Tail) {
            int l = fread(buffer, 1, BufferSize, stdin);
            Tail = (Head = buffer) + l;
        }
        return *Head++;
    }
    LL read() {
        LL x = 0, f = 1; char c = Getchar();
        while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
        while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
        return x * f;
    }
    
    #define maxn 50010
    #define oo 2147483647
    int n, m, Cur, ToT, root, lc[maxn], rc[maxn];
    struct Node {
    	int x[2], mx[2], mn[2]; LL val, sum;
    	bool operator < (const Node& t) const { return x[Cur] < t.x[Cur]; }
    } nodes[maxn];
    
    void maintain(int o) {
    	int l = lc[o], r = rc[o];
    	for(int i = 0; i < 2; i++) {
    		nodes[o].mx[i] = max(max(nodes[l].mx[i], nodes[r].mx[i]), nodes[o].x[i]);
    		nodes[o].mn[i] = min(min(nodes[l].mn[i], nodes[r].mn[i]), nodes[o].x[i]);
    	}
    	nodes[o].sum = nodes[l].sum + nodes[r].sum + nodes[o].val;
    	return ;
    }
    void build(int& o, int L, int R, int cur) {
    	if(L > R){ o = 0; return ; }
    	int M = L + R >> 1; o = M;
    	Cur = cur; nth_element(nodes + L, nodes + M, nodes + R + 1);
    	build(lc[o], L, M - 1, cur ^ 1); build(rc[o], M + 1, R, cur ^ 1);
    	maintain(o);
    	return ;
    }
    
    bool tx, ty;
    int a, b;
    LL c;
    bool all(int o) {
    	tx ^= 1; ty ^= 1;
    	int xx = tx ? nodes[o].mx[0] : nodes[o].mn[0], yy = ty ? nodes[o].mx[1] : nodes[o].mn[1];
    	tx ^= 1; ty ^= 1;
    	return ((LL)a * xx + (LL)b * yy < c);
    }
    bool has(int o) {
    	int xx = tx ? nodes[o].mx[0] : nodes[o].mn[0], yy = ty ? nodes[o].mx[1] : nodes[o].mn[1];
    //	printf("%d: %d %d %d %d
    ", o, xx, yy, tx, ty);
    	return ((LL)a * xx + (LL)b * yy < c);
    }
    LL query(int o) {
    	if(!o) return 0;
    	LL ans = 0;
    //	printf("o: %d %d
    ", o, root);
    	if(all(lc[o])) ans += nodes[lc[o]].sum;
    	else if(has(lc[o])) ans += query(lc[o]);
    	if(all(rc[o])) ans += nodes[rc[o]].sum;
    	else if(has(rc[o])) ans += query(rc[o]);
    	int xx = nodes[o].x[0], yy = nodes[o].x[1];
    	if((LL)a * xx + (LL)b * yy < c) ans += nodes[o].val;
    	return ans;
    }
    
    int main() {
    	nodes[0].mx[0] = nodes[0].mx[1] = -oo;
    	nodes[0].mn[0] = nodes[0].mn[1] = oo;
    	nodes[0].sum = 0;
    	n = read(); m = read(); LL sum = 0;
    	for(int i = 1; i <= n; i++) {
    		nodes[++ToT].x[0] = read(); nodes[ToT].x[1] = read(); nodes[ToT].val = read();
    		sum += nodes[ToT].val;
    	}
    	build(root, 1, n, 0);
    	
    	while(m--) {
    		a = read(); b = read(); c = read();
    		if(a == 0 && b == 0) {
    			if(c > 0) printf("%lld
    ", sum); else puts("0");
    			continue;
    		}
    		if(a == 0 && b > 0) tx = ty = 0;
    		if(a == 0 && b < 0) tx = 0, ty = 1;
    		if(a > 0 && b == 0) tx = ty = 0;
    		if(a < 0 && b == 0) tx = ty = 1;
    		if(a > 0 && b > 0) tx = ty = 0;
    		if(a < 0 && b > 0) tx = 1, ty = 0;
    		if(a > 0 && b < 0) tx = 0, ty = 1;
    		if(a < 0 && b < 0) tx = ty = 1;
    		printf("%lld
    ", query(root));
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    ACM成长之路
    洛谷P1047 校门外的树
    洛谷P1046 陶陶摘苹果
    2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 F题
    图论:POJ2186-Popular Cows (求强连通分量)
    DFS:POJ1562-Oil Deposits(求连通块个数)
    DFS:POJ3620-Avoid The Lakes(求最基本的联通块)
    map函数的应用:UVa156-Ananagrams
    set的应用:UVa10815-Andy's First Dictionary
    水题:UVa253-Cube painting
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5578194.html
Copyright © 2011-2022 走看看