zoukankan      html  css  js  c++  java
  • Luogu P4148 简单题(K-D Tree)

    题面

    题解

    因为强制在线,所以我们不能$cdq$分治,所以考虑用$KDT$,$KDT$维护一个矩阵,然后询问的时候如果当前矩形在询问区间内,直接记贡献,否则判断当前点是否在矩阵内,然后左右分别递归下去判断就行了。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using std::min; using std::max;
    using std::nth_element;
    typedef long long ll;
    
    template<typename T>
    void read(T &x) {
        int flag = 1; x = 0; char ch = getchar();
        while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); }
        while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag;
    }
    
    const int N = 200005;
    int n, x1, x2, y1, y2, k, ans, rt, WD, top, cnt, rub[N];
    struct poi { int x[2], w; } p[N];
    struct node { int mi[2], mx[2], sum, lc, rc, siz; poi tp; } t[N];
    int operator < (const poi &a, const poi &b) { return a.x[WD] < b.x[WD]; }
    inline int newnode() { if(top) return rub[top--]; else return ++cnt; }
    void up(int k) {
    	int l = t[k].lc, r = t[k].rc;
    	for(int i = 0; i < 2; ++i) {
    		t[k].mi[i] = t[k].mx[i] = t[k].tp.x[i];
    		if(l) t[k].mi[i] = min(t[k].mi[i], t[l].mi[i]), t[k].mx[i] = max(t[k].mx[i], t[l].mx[i]);
    		if(r) t[k].mi[i] = min(t[k].mi[i], t[r].mi[i]), t[k].mx[i] = max(t[k].mx[i], t[r].mx[i]);
    	}
    	t[k].sum = t[l].sum + t[r].sum + t[k].tp.w, t[k].siz = t[l].siz + t[r].siz + 1;
    }
    int build(int l, int r, int wd) {
    	if(l > r) return 0;
    	int mid = (l + r) >> 1, k = newnode();
    	WD = wd, nth_element(p + l, p + mid, p + r + 1), t[k].tp = p[mid];
    	t[k].lc = build(l, mid - 1, wd ^ 1), t[k].rc = build(mid + 1, r, wd ^ 1);
    	up(k); return k;
    }
    void pia(int k, int num) {
    	if(t[k].lc) pia(t[k].lc, num);
    	p[t[t[k].lc].siz + num + 1] = t[k].tp, rub[++top] = k;
    	if(t[k].rc) pia(t[k].rc, num + t[t[k].lc].siz + 1);
    }
    void check(int &k, int wd) {
    	if(0.75 * t[k].siz < t[t[k].lc].siz || 0.75 * t[k].siz < t[t[k].rc].siz)
    		pia(k, 0), k = build(1, t[k].siz, wd);
    }
    void insert(int &k, poi tmp, int wd) {
    	if(!k) { k = newnode(), t[k].lc = t[k].rc = 0, t[k].tp = tmp, up(k); return ; }
    	if(tmp.x[wd] <= t[k].tp.x[wd]) insert(t[k].lc, tmp, wd ^ 1);
    	else insert(t[k].rc, tmp, wd ^ 1);
    	up(k), check(k, wd);
    }
    int in(int x1,int y1,int x2,int y2,int X1,int Y1,int X2,int Y2) { return (X1>=x1&&X2<=x2&&Y1>=y1&&Y2<=y2); }
    int out(int x1,int y1,int x2,int y2,int X1,int Y1,int X2,int Y2) { return (x1>X2||x2<X1||y1>Y2||y2<Y1); }
    int query(int k, int x1, int y1, int x2 ,int y2) {
    	if(!k) return 0;
    	int ret = 0;
    	if(in(x1, y1, x2, y2, t[k].mi[0], t[k].mi[1], t[k].mx[0], t[k].mx[1])) return t[k].sum;
    	if(out(x1, y1, x2, y2, t[k].mi[0], t[k].mi[1], t[k].mx[0], t[k].mx[1])) return 0;
    	if(in(x1, y1, x2, y2, t[k].tp.x[0], t[k].tp.x[1], t[k].tp.x[0], t[k].tp.x[1])) ret += t[k].tp.w;
    	return ret + query(t[k].lc, x1, y1, x2, y2) + query(t[k].rc, x1, y1, x2, y2);
    }
    
    int main () {
    	read(n);
    	while(true) {
    		int opt; read(opt);
    		if(opt == 3) break;
    		else {
    			read(x1), read(y1), x1 ^= ans, y1 ^= ans;
    			if(opt == 1) read(k), insert(rt, (poi){x1, y1, k ^ ans}, 0);
    			else {
    				read(x2), read(y2), x2 ^= ans, y2 ^= ans;
    				ans = query(rt, x1, y1, x2, y2), printf("%d
    ", ans);
    			}
    		}
    	}
        return 0;
    }
    
  • 相关阅读:
    iozone的三大神器之一fileop
    nginx反向代理配置相对路径
    自建yum源解决Ceph搭建过程中从官网取包慢的问题
    SourceInsight 4重启之后文件变只读无法编辑
    Android应用启动时Activity被创建两次
    mfscli的使用方法(解决mfscgi响应慢的问题)
    漫谈moosefs中cgi各项的意义
    Linux stress CPU的测试方法
    磁盘测试工具FIO工具安装和使用方法
    iperf测试工具
  • 原文地址:https://www.cnblogs.com/water-mi/p/10172376.html
Copyright © 2011-2022 走看看