题意:给定一堆点,每个点有权值,每次求在直线$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:15568 ms
  7     Memory:4220 kb
  8 ****************************************************************/
  9  
 10 #include <cstdio>
 11 #include <algorithm>
 12  
 13 using namespace std;
 14 typedef long long ll;
 15 const int N = 5e4 + 5;
 16  
 17 inline int read();
 18  
 19 int n, m;
 20 int A, B, C, D;
 21  
 22 struct point {
 23     int x[2], v;
 24      
 25     point() {}
 26      
 27     inline void get() {
 28         x[0] = read(), x[1] = read(), v = read();
 29     }
 30      
 31     int& operator [] (int i) {
 32         return x[i];
 33     }
 34     inline bool operator < (const point &p) const {
 35         return x[D] < p.x[D];
 36     }
 37 } p[N];
 38  
 39 inline bool check(int x,int y) {
 40     return A * x + B * y < C;
 41 }
 42  
 43 struct KD_tree {
 44     KD_tree *ls, *rs;
 45     point p;
 46     int mn[2], mx[2];
 47     ll sum;
 48      
 49     KD_tree() {
 50         ls = rs = NULL;
 51         p = point();
 52         sum = 0;
 53     }
 54      
 55     #define Len (1 << 16)
 56     inline void* operator new(size_t) {
 57         static KD_tree *mempool, *c;
 58         if (mempool == c)
 59             mempool = (c = new KD_tree[Len]) + Len;
 60         *c = KD_tree();
 61         return c++;
 62     }
 63     #undef Len
 64      
 65     inline int calc() {
 66         return check(mn[0], mn[1]) + check(mn[0], mx[1]) + check(mx[0], mn[1]) + check(mx[0], mx[1]);
 67     }
 68      
 69     inline void update() {
 70         static int i;
 71         for (i = 0; i < 2; ++i) {
 72             mn[i] = mx[i] = p[i];
 73             if (ls) {
 74                 mn[i] = min(mn[i], ls -> mn[i]);
 75                 mx[i] = max(mx[i], ls -> mx[i]);
 76             }
 77             if (rs) {
 78                 mn[i] = min(mn[i], rs -> mn[i]);
 79                 mx[i] = max(mx[i], rs -> mx[i]);
 80             }
 81         }
 82         sum = p.v;
 83         if (ls) sum += ls -> sum;
 84         if (rs) sum += rs -> sum;
 85     }
 86       
 87     #define mid (l + r >> 1)
 88     void build(int l, int r, int now, point *P) {
 89         D = now;
 90         nth_element(P + l, P + mid, P + r + 1);
 91         p = P[mid];
 92         if (l < mid) {
 93             ls = new()KD_tree;
 94             ls -> build(l, mid - 1, !now, P);
 95         }
 96         if (mid < r) {
 97             rs = new()KD_tree;
 98             rs -> build(mid + 1, r, !now, P);
 99         }
100         update();
101     }
102     #undef mid
103      
104     ll query() {
105         ll res = 0;
106         int cntl, cntr;
107         if (check(p[0], p[1])) res += p.v;
108         if (ls) {
109             cntl = ls -> calc();
110             if (cntl == 4) res += ls -> sum;
111             else if (cntl) res += ls -> query();
112         }
113         if (rs) {
114             cntr = rs -> calc();
115             if (cntr == 4) res += rs -> sum;
116             else if (cntr) res += rs -> query();
117         }
118         return res;
119     }
120 } *T;
121  
122 int main() {
123     int i;
124     n = read(), m = read();
125     for (i = 1; i <= n; ++i)
126         p[i].get();
127     T = new()KD_tree;
128     T -> build(1, n, 0, p);
129     while (m--) {
130         A = read(), B = read(), C = read();
131         printf("%lld\n", T -> query());
132     }
133     return 0;
134 }
135  
136 inline int read() {
137     static int x, sgn;
138     static char ch;
139     x = 0, sgn = 1, ch = getchar();
140     while (ch < '0' || '9' < ch) {
141         if (ch == '-') sgn = -1;
142         ch = getchar();
143     }
144     while ('0' <= ch && ch <= '9') {
145         x = x * 10 + ch - '0';
146         ch = getchar();
147     }
148     return sgn * x;
149 }
View Code

 

posted on 2015-05-03 22:08  Xs酱~  阅读(184)  评论(0编辑  收藏  举报