BZOJ 2850

这题,由于是在学习KD_tree的时候从黄学长那里找到的题,所以知道了它是一道KD_tree的题,不然我一定会认为它是一个半平面交维护什么鬼的。

我个人理解KD_tree就是一种玄学暴力,利用对数据的一些处理组织成了树的形式,利用估价函数进行剪枝,然后就可以比较方便的查询。

对于这道题,要求满足Ax+By<C的点对的个数,那么我们建出KD_tree,然后我们的估价函数就是如果这个子树内的所有点都满足或不满足,我们就直接返回答案,否则就递归到左右子树,感觉KD_tree的复杂度还是很玄学的...

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 #define maxn 50005
  6 typedef long long LL;
  7 struct KD_tree
  8 {
  9     int ls,rs,mx[2],mn[2],d[2],key;
 10     LL sum;
 11 }t[maxn];
 12 int n,m,cmp_d,rt;
 13 LL A,B,C;
 14 
 15 inline int read(void) 
 16 {
 17     int x=0,f=1;
 18     char ch=getchar();
 19     while (ch>'9'||ch<'0') 
 20     {
 21         if (ch=='-') f=-1;
 22         ch=getchar();
 23     }
 24     while (ch>='0'&&ch<='9') 
 25     {
 26         x=x*10+ch-'0';
 27         ch=getchar();
 28     }
 29     return x*f;
 30 }
 31 
 32 void KD_update(int x)
 33 {
 34     int ls=t[x].ls;
 35     int rs=t[x].rs;
 36     if (ls) 
 37     {
 38         t[x].mx[0]=max(t[x].mx[0],t[ls].mx[0]);
 39         t[x].mx[1]=max(t[x].mx[1],t[ls].mx[1]);
 40         t[x].mn[0]=min(t[x].mn[0],t[ls].mn[0]);
 41         t[x].mn[1]=min(t[x].mn[1],t[ls].mn[1]);
 42     }
 43     if (rs) 
 44     {
 45         t[x].mx[0]=max(t[x].mx[0],t[rs].mx[0]);
 46         t[x].mx[1]=max(t[x].mx[1],t[rs].mx[1]);
 47         t[x].mn[0]=min(t[x].mn[0],t[rs].mn[0]);
 48         t[x].mn[1]=min(t[x].mn[1],t[rs].mn[1]);
 49     }
 50     t[x].sum=t[ls].sum+t[rs].sum+t[x].key;
 51 }
 52 
 53 inline bool cmp(KD_tree a,KD_tree b)
 54 {
 55     int x=a.d[cmp_d],y=b.d[cmp_d];
 56     return x<y||(x==y&&a.d[!cmp_d]<b.d[!cmp_d]);
 57 }
 58 
 59 int KD_build(int l,int r,int D)
 60 {
 61     int mid=(l+r)>>1;
 62     cmp_d=D;
 63     nth_element(t+l,t+mid,t+r+1,cmp);
 64     t[mid].mx[0]=t[mid].mn[0]=t[mid].d[0];
 65     t[mid].mx[1]=t[mid].mn[1]=t[mid].d[1];
 66     if (l<mid) t[mid].ls=KD_build(l,mid-1,D^1);
 67     if (r>mid) t[mid].rs=KD_build(mid+1,r,D^1);
 68     KD_update(mid);
 69     return mid;
 70 }
 71 
 72 int check(int x)
 73 {
 74     int cnt=0;
 75     cnt+= A*t[x].mn[0]+B*t[x].mn[1]<C;
 76     cnt+= A*t[x].mn[0]+B*t[x].mx[1]<C;
 77     cnt+= A*t[x].mx[0]+B*t[x].mn[1]<C;
 78     cnt+= A*t[x].mx[0]+B*t[x].mx[1]<C;
 79     return cnt;
 80 }
 81 
 82 LL KD_query(int x)
 83 {
 84     int cnt=check(x);
 85     if (cnt==4) return t[x].sum;
 86     if (cnt==0) return 0;
 87     LL tmp=0;
 88     if (A*t[x].d[0]+B*t[x].d[1]<C) tmp=t[x].key;
 89     if (t[x].ls) tmp+=KD_query(t[x].ls);
 90     if (t[x].rs) tmp+=KD_query(t[x].rs);
 91     return tmp;
 92 }
 93 
 94 int main()
 95 {
 96     n=read();m=read();
 97     for (int i=1;i<=n;i++) 
 98         t[i].d[0]=read(),t[i].d[1]=read(),t[i].key=read();
 99     rt=KD_build(1,n,0);
100     for (int i=1;i<=m;i++) 
101     {
102         A=read();B=read();C=read();
103         printf("%lld\n",KD_query(rt));
104     }
105     return 0;
106 }

 

转载于:https://www.cnblogs.com/lvyouyw/p/6857587.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BZOJ 2908 题目是一个数据下载任务。这个任务要求下载指定的数据文件,并统计文件中小于等于给定整数的数字个数。 为了完成这个任务,首先需要选择一个合适的网址来下载文件。我们可以使用一个网络爬虫库,如Python中的Requests库,来帮助我们完成文件下载的操作。 首先,我们需要使用Requests库中的get()方法来访问目标网址,并将目标文件下载到我们的本地计算机中。可以使用以下代码实现文件下载: ```python import requests url = '目标文件的网址' response = requests.get(url) with open('本地保存文件的路径', 'wb') as file: file.write(response.content) ``` 下载完成后,我们可以使用Python内置的open()函数打开已下载的文件,并按行读取文件内容。可以使用以下代码实现文件内容读取: ```python count = 0 with open('本地保存文件的路径', 'r') as file: for line in file: # 在这里实现对每一行数据的判断 # 如果小于等于给定整数,count 加 1 # 否则,不进行任何操作 ``` 在每一行的处理过程中,我们可以使用split()方法将一行数据分割成多个字符串,并使用int()函数将其转换为整数。然后,我们可以将该整数与给定整数进行比较,以判断是否小于等于给定整数。 最后,我们可以将统计结果打印出来,以满足题目的要求。 综上所述,以上是关于解决 BZOJ 2908 数据下载任务的简要步骤和代码实现。 希望对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值