[Luogu4475]巧克力王国

luogu

题意

平面上有\(n\)个点,每个点\((x_i,y_i)\),价值为\(w_i\)。\(m\)次询问,每次给出\(a_i,b_i,c_i\)求满足\(a_ix+b_iy<c_i\)的点的总价值。
\(n,m\le50000\)

sol

正解貌似是\(O(n^{1.5}\log n)\)?
我只会\(kdt\)qaq
直接暴力就行了,每到一个结点判断是否可以直接返回(交集为空),全部算上(完全包含与查询范围),算是剪枝吧。

code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi(){
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=0,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return w?x:-x;
}
#define ll long long
#define ls t[o].ch[0]
#define rs t[o].ch[1]
#define cmin(a,b) (a>b?a=b:a)
#define cmax(a,b) (a<b?a=b:a)
const int N = 5e4+5;
int n,m,D,root;ll ans;
struct node{
    int d[2],key;
    bool operator < (const node &b) const
        {return d[D]<b.d[D];}
}a[N];
struct kdtree{int d[2],Min[2],Max[2],ch[2];ll sum;}t[N];
void mt(int x,int y){
    cmin(t[x].Min[0],t[y].Min[0]);cmax(t[x].Max[0],t[y].Max[0]);
    cmin(t[x].Min[1],t[y].Min[1]);cmax(t[x].Max[1],t[y].Max[1]);
    t[x].sum+=t[y].sum;
}
int build(int l,int r,int d){
    D=d;int o=l+r>>1;
    nth_element(a+l,a+o,a+r+1);
    t[o].d[0]=t[o].Min[0]=t[o].Max[0]=a[o].d[0];
    t[o].d[1]=t[o].Min[1]=t[o].Max[1]=a[o].d[1];
    t[o].sum=a[o].key;
    if (l<o) ls=build(l,o-1,d^1),mt(o,ls);
    if (o<r) rs=build(o+1,r,d^1),mt(o,rs);
    return o;
}
inline bool empty(int o,int x,int y,int z){
    if (1ll*t[o].Min[0]*x+1ll*t[o].Min[1]*y<z) return 0;
    if (1ll*t[o].Min[0]*x+1ll*t[o].Max[1]*y<z) return 0;
    if (1ll*t[o].Max[0]*x+1ll*t[o].Min[1]*y<z) return 0;
    if (1ll*t[o].Max[0]*x+1ll*t[o].Max[1]*y<z) return 0;
    return 1;
}
inline bool whole(int o,int x,int y,int z){
    if (1ll*t[o].Min[0]*x+1ll*t[o].Min[1]*y>=z) return 0;
    if (1ll*t[o].Min[0]*x+1ll*t[o].Max[1]*y>=z) return 0;
    if (1ll*t[o].Max[0]*x+1ll*t[o].Min[1]*y>=z) return 0;
    if (1ll*t[o].Max[0]*x+1ll*t[o].Max[1]*y>=z) return 0;
    return 1;
}
inline bool in(int o,int x,int y,int z){
    return 1ll*t[o].d[0]*x+1ll*t[o].d[1]*y<z;
}
void query(int o,int x,int y,int z){
    if (empty(o,x,y,z)) return;
    if (whole(o,x,y,z)) {ans+=t[o].sum;return;}
    if (in(o,x,y,z)) ans+=a[o].key;
    if (ls) query(ls,x,y,z);if (rs) query(rs,x,y,z);
}
int main(){
    n=gi();m=gi();
    for (int i=1;i<=n;++i) a[i]=(node){gi(),gi(),gi()};
    root=build(1,n,0);
    while (m--){
        int x=gi(),y=gi(),z=gi();ans=0;
        query(root,x,y,z);printf("%lld\n",ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/zhoushuyu/p/9077973.html

时间: 2024-08-30 01:32:07

[Luogu4475]巧克力王国的相关文章

【BZOJ2850】巧克力王国 KDtree

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

bzoj2850巧克力王国*

bzoj2850巧克力王国 题意: n个巧克力,每个有牛奶含量,可可含量和美味值.m个人,每个有三个权值a,b,c,如果某个巧克力的牛奶含量*a+可可含量*b<c就可以接受.问每个人能接受的巧克力美味值之和.n,m≤50000. 题解: 对所有巧克力建kd树,树上节点除了维护子树横纵坐标最大最小值还要维护子树美味值之和.在查询时如果估价得出这个子树的牛奶含量最大值乘a+可可含量最大值*b小于c则整棵子树都能接受,否则只要该子树可能有机会存在可接受巧克力就遍历这棵子树. 代码: 1 #includ

【bzoj2850】巧克力王国 KD-tree

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

【BZOJ】【2850】【Violet 0】巧克力王国

KD-Tree 问平面内在某条直线下方的点的权值和 我一开始yy的是:直接判这个矩形最高的两个点(y坐标的最大值)是否在这条直线下方就可以了~即判$A*x+B*y<C$... 然而这并不对啊……因为你得分类讨论啊……不能直接判那个式子的啊…… 膜拜了hzwer的姿势:四个角都判,那么这样就避免了分类讨论……轻松+愉快 今天突然发现:KD-Tree是会Push_up叶子节点的,这点跟线段树不一样……QAQ怪不得以前模板那样写是错的…… 另外,鉴于上一题出了个讨厌的bug,我换了种姿势来push_u

P4475 巧克力王国(KDTree)

传送门 首先可以把约束条件看成一条直线,然后每个巧克力看成一个点,求给定区域内的点权和 用KDTree,每次判断一下当前矩形是否整个都在里面或都在外面,是的话直接返回,否则的话递归 注意,必须该矩形四个顶点都在里面或外面才能判断 //minamoto #include<bits/stdc++.h> #define R register #define ll long long #define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i) #define f

【kd-tree】bzoj2850 巧克力王国

分四种情况讨论:a,b>=0 a,b<0 a>=0,b<0 a<0,b>=0 然后每次检验是否进入一个矩形框 或者 是否直接利用这个矩形框的答案 仅仅利用两个对角的坐标进行更新即可. #include<cstdio> #include<cmath> #include<algorithm> using namespace std; typedef long long ll; #define N 50001 #define INF 214

BZOJ2850 巧克力王国

题意:给定一堆点,每个点有权值,每次求在直线$Ax + By + C = 0$下的点的权值和 KD树维护一下二维区间内的点权和就好恩...建树复杂度$O(n * logn)$,单次查询时间$O(\sqrt{n})$ 1 /************************************************************** 2 Problem: 2850 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:155

【题解】巧克力王国

题目链接 题目大意,求在给定要求内的数据之和. 挺简洁的,一样对于数据建树,维护一个\(sum\)美味度的和,上下界变成甜度,\(query\)时判断是不是满足客户甜度要求,如果四种搭配\((mi[0]->mx[1],mi[0]->mi[1],mx[0]->mi[1],mx[0]->mx[1])\) 均符合要求,则说明这整个区间答案都属于贡献,直接加\(sum\)即可. 否则,判断一波当前走到的点能不能贡献,然后分左右查询即可. #include<cstdio> #in

YCB 的暑期计划

前言 YCB现在很弱(TAT) 暑假有一个月,赶快狂补一下. 大概的计划如下: 首先前期会以数据结构为主,毕竟代码能力太弱,涉及内容:线段树分治.二进制分组.KD-Tree. 等数据结构做到没有智商的时候加入一波数论,内容为 杜教筛.min_25筛. 然后中途小清新一下,做一些 组合博弈与构造题. 接着继续练代码能力,顺便学一些神奇的暴力:启发式合并.dsu on tree . 然后图论也忘的差不多了,就回过头去学点新东西,大概会有spfa判负环.0/1分数规划.差分约束. 估计这个时候也没有什