zoukankan      html  css  js  c++  java
  • JZOJ 5067. 【GDOI2017第二轮模拟day2】有理有据题 (KD-tree+历史最值问题)

    https://gmoj.net/senior/#main/show/5067

    题解:

    考虑([l,r]∩[x,y] e ∅)的充要条件是(max(l,x)le min(r,y))
    (l le y且 x le r)

    那么每次相当于修改矩形内的点。

    套上一个K-D tree,问题变成了:

    1. 区间加
    2. 区间赋值
    3. 询问单点历史最大值

    这个可以直接lazytag搞定,通过思考一个操作序列需要保留什么东西即可实现。

    Code:

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    const int N = 50005;
    
    int n, m, Q;
    
    struct P {
    	int x, y, i;
    } a[N];
    
    void Init() {
    	scanf("%d %d %d", &n, &m, &Q);
    	fo(i, 1, n) {
    		scanf("%d %d", &a[i].x, &a[i].y);
    		if(a[i].x > a[i].y) swap(a[i].x, a[i].y);
    		a[i].y = -a[i].y;
    		swap(a[i].x, a[i].y);
    		a[i].i = i;
    	}
    }
    
    struct nod {
    	bool bz;
    	int m1, m2, s;
    	nod() { bz = m1 = m2 = s = 0;}
    };
    
    void jia(nod &a, int v) {
    	if(!a.bz) {
    		a.s += v;
    		a.m1 = max(a.m1, a.s);
    	} else {
    		a.s += v;
    		a.m2 = max(a.m2, a.s);
    	}
    }
    
    void fz(nod &a) {
    	a.bz = 1;
    	a.s = 0;
    }
    
    void mer(nod &a, nod b) {
    	if(!a.bz) {
    		if(!b.bz) {
    			a.bz = 0;
    			a.m1 = max(a.m1, a.s + b.m1);
    			a.s += b.s;
    		} else {
    			a.bz = 1;
    			a.m1 = max(a.m1, a.s + b.m1); 
    			a.m2 = b.m2;
    			a.s = b.s;
    		}
    	} else {
    		if(!b.bz) {
    			a.bz = 1;
    			a.m2 = max(a.m2, a.s + b.m1);
    			a.s += b.s;
    		} else {
    			a.bz = 1;
    			a.m2 = max(a.m2, max(a.s + b.m1, b.m2));
    			a.s = b.s;
    		}
    	}
    }
    
    #define i0 i + i
    #define i1 i + i + 1
    
    struct tree {
    	int mi[2], mx[2];
    	nod v;
    } t[N * 4];
    int rt = 1;
    
    int o;
    int cmp(P a, P b) {
    	return o ? a.y < b.y : a.x < b.x;
    }
    
    int ia[N];
    
    #define db double
    int ca(int x, int y) {
    	db s1 = 0, s2 = 0;
    	fo(i, x, y) {
    		s1 += a[i].x;
    		s2 += a[i].y;
    	}
    	s1 /= (y - x + 1);
    	s2 /= (y - x + 1);
    	db v1 = 0, v2 = 0;
    	#define sqr(x) ((x) * (x))
    	fo(i, x, y) {
    		v1 += sqr(a[i].x - s1);
    		v2 += sqr(a[i].y - s2);
    	}
    	return v1 > v2 ? 0 : 1;
    }
    
    void bt(int i, int x, int y) {
    	if(x == y) {
    		t[i].mi[0] = t[i].mx[0] = a[x].x;
    		t[i].mi[1] = t[i].mx[1] = a[x].y;
    		ia[a[x].i] = x;
    		return;
    	}
    	o = ca(x, y)	;
    	int m = x + y >> 1;
    	nth_element(a + x, a + m, a + y + 1, cmp);
    	
    	bt(i0, x, m); bt(i1, m + 1, y);
    	
    	fo(j, 0, 1) {
    		t[i].mi[j] = min(t[i0].mi[j], t[i1].mi[j]);
    		t[i].mx[j] = max(t[i0].mx[j], t[i1].mx[j]);
    	}
    }
    
    void down(int i) {
    	if(t[i].v.bz || t[i].v.m1 || t[i].v.s) {
    		mer(t[i0].v, t[i].v);
    		mer(t[i1].v, t[i].v);
    		t[i].v = nod();
    	}
    }
    
    int pl[2], pr[2];
    
    void add(int i, int x, int y) {
    	if(t[i].mi[0] > pr[0] || t[i].mi[1] > pr[1]) {
    		fz(t[i].v);
    		return;
    	}
    	if(t[i].mx[0] <= pr[0] && t[i].mx[1] <= pr[1]) {
    		jia(t[i].v, 1);
    		return;
    	}
    	int m = x + y >> 1; down(i);
    	add(i0, x, m); add(i1, m + 1, y);
    }
    
    int pz, px;
    
    void ft(int i, int x, int y) {
    	if(x == y) {
    		px = max(t[i].v.m1, t[i].v.m2);
    		return;
    	}
    	int m = x + y >> 1; down(i);
    	if(pz <= m) ft(i0, x, m); else ft(i1, m + 1, y);
    }
    
    char str[11];
    int x, y;
    
    void cz(int x, int y) {
    	if(x > y) swap(x, y);
    	x = -x;
    	pl[0] = pl[1] = -1e9;
    	pr[0] = x, pr[1] = y;
    	add(rt, 1, n);
    }
    
    int qry(int x) {
    	pz = ia[x]; px = 0;
    	ft(rt, 1, n);
    }
    
    void End() {
    	fo(i, 1, m) {
    		scanf("%d %d", &x, &y);
    		cz(x, y);
    	}
    	fo(i, 1, Q) {
    		scanf("%s", str + 1);
    		if(str[1] == 'A') {
    			scanf("%d %d", &x, &y);
    			cz(x, y);
    		}
    		if(str[1] == 'C') {
    			scanf("%d", &x);
    			pp("%d
    ", qry(x));
    		}
    		if(str[1] == 'Q') {
    			int s = 0;
    			fo(j, 1, n) s ^= qry(j);
    			pp("%d
    ", s);
    		}
    	}
    }
    
    int main() {
    	freopen("bomb.in", "r", stdin);
    	freopen("bomb.out", "w", stdout);
    	Init();
    	bt(rt, 1, n);
    	End();
    }
    
  • 相关阅读:
    机器学习之——正规方程法
    机器学习之——学习率
    机器学习之梯度下降法
    机器学习之线性回归算法
    集体智慧编程学习笔记——第一讲
    机器学习之归一化和标准化总结
    推荐系统实战-学习笔记第一章
    洛谷P1396 营救 题解
    洛谷P3905 道路重建
    洛谷P2384 最短路 题解
  • 原文地址:https://www.cnblogs.com/coldchair/p/13456949.html
Copyright © 2011-2022 走看看