• 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 }
  • 相关阅读:
    致DBA:为什么你经常犯错,是因为你做的功课不够
    Hbase的shell命令学习
    mysql通过拷贝文件实现数据快速迁移实例
    项目领导力学习总结
    放权,从鞋柜开始
    不抱怨的世界
    定投我们自己
    mysql core文件的正确打开姿势
    2017小目标
    世界是有生命的(通向财富自由之路学习笔记十五)
  • 原文地址:https://www.cnblogs.com/lvyouyw/p/6857587.html
Copyright © 2020-2023  润新知