洛谷4475 巧克力王国(KD-Tree + 维护子树和)
(嘤嘤嘤 又是一个自闭了一晚上的题)
qwq果然不是平面上的点的问题,也可以直接用KDTree打暴力
我们对于巧克力直接建kdtree
维护一个\(mx[i],mn[i]\)
但是有一个非常不友好的事情
我们貌似很难对这个东西进行一些实质上的剪枝
因为他求的是一个和的形式,而不是一个最值QWQ
那么该怎么办呢?
我们这时候考虑,对于一个kdtree上的每一个节点,我们都维护一个子树sum表示子树内的所有巧克力的权值之和。
那么对于一次\(query\),假设我们最大的甜度都不会超过\(c\)的话,那就代表我们可以直接把这个子树的\(sum\)加进\(ans\)里面了,因为他是一定能合法的
int getsum(cho a,peo b)
{
if (!a.num) return 1e9;
int tmp =0;
for (int i=0;i<=1;i++)
tmp=tmp+a.d[i]*b.d[i];
return tmp;
}
int calc(cho a,peo b)
{
if (!a.num) return 1e9;
int tmp =0;
for (int i=0;i<=1;i++)
tmp=tmp+min(a.mn[i]*b.d[i],a.mx[i]*b.d[i]);
return tmp;
}
int getmax(cho a,peo b)
{
if (!a.num) return 1e9;
int tmp = 0;
for (int i=0;i<=1;i++)
tmp=tmp+max(a.mx[i]*b.d[i],a.mn[i]*b.d[i]);
return tmp;
}
void query(int x)
{
if (!x) return;
if (getmax(t[x],now)<now.c)
{
tmp=tmp+t[x].sum;
return;
}
int c = now.c;
int d1 = calc(t[t[x].l],now);
int d2 = calc(t[t[x].r],now);
int d = getsum(t[x],now);
if (d<now.c) tmp=tmp+t[x].val;
if (d1<c) query(t[x].l);
if (d2<c) query(t[x].r);
}
那么其实剩下的问题也就迎刃而解了
直接上代码吧
// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define mk makr_pair
#define ll long long
#define int long long
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 3e6+1e2;
struct cho{
int mn[2],mx[2];
int d[2];
int l,r;
int val;
int sum;
int num;
};
struct peo{
int d[2],c;
};
cho t[maxn];
peo now;
int n,m,root;
int sum;
int ymh;
int tmp;
bool operator < (cho a,cho b)
{
return a.d[ymh]<b.d[ymh];
}
void up(int root)
{
for (int i=0;i<=1;i++)
{
if (t[root].l)
{
t[root].mn[i]=min(t[root].mn[i],t[t[root].l].mn[i]);
t[root].mx[i]=max(t[root].mx[i],t[t[root].l].mx[i]);
}
if (t[root].r)
{
t[root].mn[i]=min(t[root].mn[i],t[t[root].r].mn[i]);
t[root].mx[i]=max(t[root].mx[i],t[t[root].r].mx[i]);
}
}
t[root].sum=t[root].val+t[t[root].l].sum+t[t[root].r].sum;
}
void build(int &x,int l,int r,int dd)
{
//cout<<1<<endl;
ymh = dd;
int mid = l+r >> 1;
x = mid;
nth_element(t+l,t+x,t+r+1);
for (int i=0;i<=1;i++) t[x].mn[i]=t[x].mx[i]=t[x].d[i];
if (l<x) build(t[x].l,l,mid-1,dd^1);
if (r>x) build(t[x].r,mid+1,r,dd^1);
up(x);
}
int getsum(cho a,peo b)
{
if (!a.num) return 1e9;
int tmp =0;
for (int i=0;i<=1;i++)
tmp=tmp+a.d[i]*b.d[i];
return tmp;
}
int calc(cho a,peo b)
{
if (!a.num) return 1e9;
int tmp =0;
for (int i=0;i<=1;i++)
tmp=tmp+min(a.mn[i]*b.d[i],a.mx[i]*b.d[i]);
return tmp;
}
int getmax(cho a,peo b)
{
if (!a.num) return 1e9;
int tmp = 0;
for (int i=0;i<=1;i++)
tmp=tmp+max(a.mx[i]*b.d[i],a.mn[i]*b.d[i]);
return tmp;
}
void query(int x)
{
if (!x) return;
if (getmax(t[x],now)<now.c)
{
tmp=tmp+t[x].sum;
return;
}
int c = now.c;
int d1 = calc(t[t[x].l],now);
int d2 = calc(t[t[x].r],now);
int d = getsum(t[x],now);
if (d<now.c) tmp=tmp+t[x].val;
if (d1<c) query(t[x].l);
if (d2<c) query(t[x].r);
}
signed main()
{
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
n=read(),m=read();
for (int i=1;i<=n;i++)
{
for(int j=0;j<=1;j++) t[i].d[j]=read();
t[i].val=read();
t[i].num=i;
}
build(root,1,n,0);
for(int i=1;i<=m;i++){
now.d[0]=read();
now.d[1]=read();
now.c=read();
tmp=0;
query(root);
cout<<tmp<<"\n";
}
return 0;
}
不过总的来说
kdtree真的是一个很优雅的暴力啊!
嘤嘤嘤
洛谷4475 巧克力王国(KD-Tree + 维护子树和)的更多相关文章
- 洛谷P4475 巧克力王国
洛谷P4475 巧克力王国 题目描述 巧克力王国里的巧克力都是由牛奶和可可做成的. 但是并不是每一块巧克力都受王国人民的欢迎,因为大家都不喜欢过于甜的巧克力. 对于每一块巧克力,我们设 x 和 y 为 ...
- 洛谷 P4475 巧克力王国 解题报告
P4475 巧克力王国 题目描述 巧克力王国里的巧克力都是由牛奶和可可做成的.但是并不是每一块巧克力都受王国人民的欢迎,因为大家都不喜欢过于甜的巧克力. 对于每一块巧克力,我们设 \(x\) 和 \( ...
- P4475 巧克力王国 k-d tree
思路:\(k-d\ tree\) 提交:2次 错因:\(query\)时有一个\(mx\)误写成\(mn\)窝太菜了. 题解: 先把\(k-d\ tree\)建出来,然后查询时判一下整个矩形是否整体\ ...
- 洛谷P3018 [USACO11MAR]树装饰Tree Decoration
洛谷P3018 [USACO11MAR]树装饰Tree Decoration树形DP 因为要求最小,我们就贪心地用每个子树中的最小cost来支付就行了 #include <bits/stdc++ ...
- 【洛谷1501】[国家集训队] Tree II(LCT维护懒惰标记)
点此看题面 大致题意: 有一棵初始边权全为\(1\)的树,四种操作:将两点间路径边权都加上一个数,删一条边.加一条新边,将两点间路径边权都加上一个数,询问两点间路径权值和. 序列版 这道题有一个序列版 ...
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
- 洛谷P2633 Count on a tree(主席树上树)
题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个 ...
- 洛谷P2633 Count on a tree(主席树,倍增LCA)
洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...
- 洛谷P2633 Count on a tree(主席树,倍增LCA,树上差分)
洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...
随机推荐
- Learning ROS: Ubuntu16.04下kinetic开发环境安装和初体验 Install + Configure + Navigating(look around) + Creating a Package(catkin_create_pkg) + Building a Package(catkin_make) + Understanding Nodes
本文主要部分来源于ROS官网的Tutorials. Ubuntu install of ROS Kinetic # Setup your sources.list sudo sh -c 'echo & ...
- Excel 快速跳转到工作表
新建 vba 模块 Sub GotoSheet() tname = InputBox("input table name") If StrPtr(tname) = 0 Then E ...
- javaScript知识储备
javaScript知识储备 组成 ECMAScript(核心) 提供语法.变量等,遵循ECMA-262标准 DOM(文档对象模型) 提供操作HTML标签的API,遵循W3C规范 BOM(浏览器对象模 ...
- 10分钟学会Visual Studio将自己创建的类库打包到NuGet进行引用(net,net core,C#)
前言 NuGet就是一个包(package)管理平台,确切的说是 .net平台的包管理工具,它提供了一系列客户端用于生成,上传和使用包(package),以及一个用于存储所有包的中心库. 对于一个现代 ...
- [编译] 10、kconfig 入门指导教程
目录 前言 1. 安装 kconfig 2. 克隆一个 demo 3. 运行 kconfig 4. 源码解析 4.1 选择题目设计模板 4.2 填空题目设计模板 4.3 判断题目设计模板 5. 产物解 ...
- 2021秋 noip 模拟赛
9.9 T3 第负二题 \(f_i\) 的数学意义:中心在第 \(i\) 行的全 \(1\) 组成的最大正方形(对角线水平/竖直),对角线长 \(2f_i-1\). 显然 \(f_i\) 具有单调性( ...
- 20210719 noip20
考场 后两题是原题,教练说不用写了(ycx 不讲武德) T1 先手模了 \(n\le5\) 的情况,尝试找规律失败.那就只能 DP 了,最终没搞出来. 记忆化搜索打了 \(n\le20\) 的表,交了 ...
- Asp.net Core Jwt简单使用
.net 默认新建Api项目不需要额外从Nuget添加Microsoft.AspNetCore.Authentication.JwtBearer appsettings.json { "Lo ...
- Devexpress主题/皮肤
如何在C#中使用DevExpress皮肤管理器.步骤1: 单击 新建项目,然后选择左侧的Visual C#,然后 视窗 ,然后选择 Windows窗体应用程序.将您的项目命名为" SkinD ...
- Redis单节点安装与使用
1.配置阿里云yum源 下载配置文件 wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7 ...