bzoj4520k远点对(堆乱搞2*k个值)
剪枝:判断点到矩形距离与堆顶的关系。
//任意两点对
ll gdis(node a,node now){
ll res=0;
res+=max(sqr(a.mn[0]-now.d[0]),sqr(a.mx[0]-now.d[0]));
res+=max(sqr(a.mn[1]-now.d[1]),sqr(a.mx[1]-now.d[1]));
return res;
}
bzoj2850√Ax+By<C
剪枝:判断一个矩形内是否一定全都合法(直接加sum)。
bzoj4605
bzoj2716&&2648插入点时要每插入n√个点重构一次
剪枝:判断点到矩形距离与答案的关系
//查询一个点到另一个点的最短曼哈顿距离
int gdis(node a,node now){
//询问的当前点到搞到的kd-tree的矩形的距离
int res=0;
for (int i=0;i<=1;i++){
res+=max(0,now.d[i]-a.mx[i]);
res+=max(0,a.mn[i]-now.d[i]);
}
return res;
}
bzoj3053k[1~5]维,输出m近点对。
剪枝:判断点到矩形距离与堆顶的关系。
给定一个点,弄另一个点。
ll gdis(node a,pd now){
ll res=0;
for (int i=0;i<m;i++){
if (now.c[i]<a.mn[i])
res+=sqr(now.c[i]-a.mn[i]);
if (now.c[i]>a.mx[i])
res+=sqr(now.c[i]-a.mx[i]);
}
return res;
}
bzoj4066&&2683
bzoj2626 二维第k远点
bzoj3489 三维,第一维是这个数上一次出现位置,第二维是当前位置,第三维是下一次出现位置
bzoj1941二维,搞出每个点的最远距离和最近距离
bzoj4130
bzoj3616
bzoj4154
题意:
给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过len的a的子节点染成c,或询问点a的颜色
分析:
将每个树上节点变为平面上的点(dfs序,点到根的距离)
对于每个修改,就将平面x轴:[节点开始的dfs序,节点结束的dfs序],y轴:[dep[x],dep[x]+len]。区间包含的就打tag,tag要下传后清空
对于每个询问,就看当前区间是否包含该节点且有整个区间的tag,不然就暴搞进去。
bzoj4170
bzoj4538
bzoj1790
bzoj4553
//bzoj2850
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=50010;
int n,m,F,root;
ll x,y,z,ans;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct node{
int d[2],mn[2],mx[2],v,l,r;
ll sum;
friend bool operator < (node a,node b){
return a.d[F]<b.d[F];
}
}p[N];
int check(int a,int b){
return x*a+y*b<z;
}
int calc(node a){
int res=0;
res+=check(a.mn[0],a.mn[1]);
res+=check(a.mn[0],a.mx[1]);
res+=check(a.mx[0],a.mn[1]);
res+=check(a.mx[0],a.mx[1]);
return res;
}
struct kd_tree{
node t[N];
void pushup(int rt){
int l=t[rt].l,r=t[rt].r;
for (int i=0;i<=1;i++){
t[rt].mx[i]=t[rt].mn[i]=t[rt].d[i];
if (l) t[rt].mn[i]=min(t[rt].mn[i],t[l].mn[i]);
if (r) t[rt].mx[i]=max(t[rt].mx[i],t[r].mx[i]);
if (l) t[rt].mx[i]=max(t[rt].mx[i],t[l].mx[i]);
if (r) t[rt].mn[i]=min(t[rt].mn[i],t[r].mn[i]);
}
t[rt].sum=t[rt].v+t[l].sum+t[r].sum;
}
int build(int l,int r,int now){
/*
用方差决定是切割哪一维
double _x=0,_y=0;
F(i,l,r)
_x+=t[i].d[0],
_y+=t[i].d[1];
_x/=r-l+1,_y/=r-l+1;
double x_=0,y_=0;
x_+=sqr(t[i].d[0]-_x),
y_+=sqr(t[i].d[1]-_y);
F=y_>x_;
*/
F=now;int mid=(l+r)>>1;
nth_element(p+l,p+mid,p+r+1);
t[mid]=p[mid];
if (l<mid) t[mid].l=build(l,mid-1,now^1);
if (r>mid) t[mid].r=build(mid+1,r,now^1);
pushup(mid);return mid;
}
void query(int rt){
int l=t[rt].l,r=t[rt].r;
if (check(t[rt].d[0],t[rt].d[1]))
ans+=t[rt].v;
if (l){
int tl=calc(t[l]);
if (tl==4)
ans+=t[l].sum; else
if (tl)
query(l);
}
if (r){
int tr=calc(t[r]);
if (tr==4)
ans+=t[r].sum; else
if (tr)
query(r);
}
}
}tree;
int main(){
freopen("d.in","r",stdin);
n=read();m=read();
for (int i=1;i<=n;i++){
p[i].d[0]=read();
p[i].d[1]=read();
p[i].v=read();
}
root=tree.build(1,n,0);
while (m--){
x=read();
y=read();
z=read();
ans=0;
tree.query(root);
printf("%lld\n",ans);
}
}