• #4864. [BeiJing 2017 Wc]神秘物质 [FHQ Treap]


    这题其实挺简单的,有个东西可能稍微难维护了一点点。。

    (merge x e) 当前第 (x) 个原子和第 (x+1) 个原子合并,得到能量为 (e) 的新原子;
    (insert x e) 在当前第 (x) 个原子和第 (x+1) 个原子之间插入一个能量为 (e) 的新原子。
    (max x y) 当前第 (x) 到第 (y) 个原子之间的任意子区间中区间极差的最大值;
    (min x y) 当前第 (x) 到第 (y) 个原子之间的任意子区间中区间极差的最小值。

    极差最大值其实很显然是个区间 (max - min)
    极差最小的区间呢,长度至少为 (2) 也必须为 (2)
    至于证明的话
    考虑 (x,y,z)

    如果 (x)(z) 的差的绝对值是解,那么 (|x-y|) 或者 (|y-z|) 一定更优

    因为 (x leq y leq z) 才符合这种情况。

    所以随便写写,把相邻两个的差变成后一个点的值,随便写写就可以了。

    // by Isaunoya
    #include <bits/stdc++.h>
    using namespace std;
    #define rep(i, x, y) for (register int i = (x); i <= (y); ++i)
    #define Rep(i, x, y) for (register int i = (x); i >= (y); --i)
    
    const int _ = 1 << 21;
    struct I {
    	char fin[_], *p1 = fin, *p2 = fin;
    	inline char gc() {
    		return (p1 == p2) && (p2 = (p1 = fin) + fread(fin, 1, _, stdin), p1 == p2) ? EOF : *p1++;
    	}
    	inline I& operator>>(int& x) {
    		bool sign = 1;
    		char c = 0;
    		while (c < 48) ((c = gc()) == 45) && (sign = 0);
    		x = (c & 15);
    		while ((c = gc()) > 47) x = (x << 1) + (x << 3) + (c & 15);
    		x = sign ? x : -x;
    		return *this;
    	}
    	inline I& operator>>(double& x) {
    		bool sign = 1;
    		char c = 0;
    		while (c < 48) ((c = gc()) == 45) && (sign = 0);
    		x = (c - 48);
    		while ((c = gc()) > 47) x = x * 10 + (c - 48);
    		if (c == '.') {
    			double d = 1.0;
    			while ((c = gc()) > 47) d = d * 0.1, x = x + (d * (c - 48));
    		}
    		x = sign ? x : -x;
    		return *this;
    	}
    	inline I& operator>>(char& x) {
    		do
    			x = gc();
    		while (isspace(x));
    		return *this;
    	}
    	inline I& operator>>(string& s) {
    		s = "";
    		char c = gc();
    		while (isspace(c)) c = gc();
    		while (!isspace(c) && c != EOF) s += c, c = gc();
    		return *this;
    	}
    } in;
    struct O {
    	char st[100], fout[_];
    	signed stk = 0, top = 0;
    	inline void flush() {
    		fwrite(fout, 1, top, stdout), fflush(stdout), top = 0;
    	}
    	inline O& operator<<(int x) {
    		if (top > (1 << 20)) flush();
    		if (x < 0) fout[top++] = 45, x = -x;
    		do
    			st[++stk] = x % 10 ^ 48, x /= 10;
    		while (x);
    		while (stk) fout[top++] = st[stk--];
    		return *this;
    	}
    	inline O& operator<<(char x) {
    		fout[top++] = x;
    		return *this;
    	}
    	inline O& operator<<(string s) {
    		if (top > (1 << 20)) flush();
    		for (char x : s) fout[top++] = x;
    		return *this;
    	}
    } out;
    #define pb emplace_back
    #define fir first
    #define sec second
    
    template < class T > inline void cmax(T & x , const T & y) {
    	(x < y) && (x = y) ;
    }
    template < class T > inline void cmin(T & x , const T & y) {
    	(x > y) && (x = y) ;
    }
    
    
    int n , m , rt = 0 ;
    const int N = 2e5 + 10 ;
    int a[N] ;
    const int inf = 0x7fffffff ;
    int rnd[N] , val[N] , mx[N] , mn[N] , ch[N][2] , sz[N] ;
    int cnt = 0 ;
    #define ls(x) ch[x][0]
    #define rs(x) ch[x][1]
    int newnode(int v) {
    	++ cnt ;
    	val[cnt] = mx[cnt] = mn[cnt] = v ;
    	rnd[cnt] = rand() ;
    	sz[cnt] = 1 ;
    	return cnt ;
    }
    int t[N] , s[N] ;
    void pushup(int rt) {
    	mx[rt] = mn[rt] = val[rt] ;
    	if(ls(rt)) cmin(mn[rt] , mn[ls(rt)]) , cmax(mx[rt] , mx[ls(rt)]) ;
    	if(rs(rt)) cmin(mn[rt] , mn[rs(rt)]) , cmax(mx[rt] , mx[rs(rt)]) ;
    	sz[rt] = sz[ls(rt)] + sz[rs(rt)] + 1 ;
    	t[rt] = min(t[ls(rt)] , t[rs(rt)]) , cmin(t[rt] , s[rt]) ;
    }
    int merge(int u , int v) {
    	if(! u || ! v) return u | v ;
    	if(rnd[u] < rnd[v]) {
    		rs(u) = merge(rs(u) , v) ;
    		pushup(u) ;
    		return u ;
    	} else {
    		ls(v) = merge(u , ls(v)) ;
    		pushup(v) ;
    		return v ;
    	}
    }
    void split(int cur , int k , int & u , int & v) {
    	if(! cur) {
    		u = v = 0 ;
    		return ;
    	}
    	if(k <= sz[ls(cur)]) {
    		v = cur ;
    		split(ls(v) , k , u , ls(v)) ;
    	} else {
    		u = cur ;
    		split(rs(u) , k - sz[ls(u)] - 1 , rs(u) , v) ;
    	}
    	pushup(cur) ;
    }
    void ins(int k , int v) {
    	int x , y , z , xx ;
    	split(rt , k - 1 , x , y) ;
    	split(y , 1 , y , z) ;
    	split(z , 1 , z , xx) ;
    	int now = newnode(v) ;
    	t[now] = s[now] = abs(val[now] - val[y]) ;
    	if(! y) {
    		t[now] = s[now] = inf ;
    	}
    	t[z] = s[z] = abs(val[z] - val[now]) ;
    	if(! z) {
    		t[z] = s[z] = inf ;
    	}
    	rt = merge(merge(merge(merge(x , y) , now) , z) , xx) ;
    }
    void _merge(int k , int v) {
    	int x , y , z , xx ;
    	split(rt , k - 1 , x , y) ;
    	split(y , 1 , y , z) ;
    	split(z , 1 , z , xx) ;
    	rt = merge(x , xx) ;
    	ins(k - 1 , v) ;
    }
    int qrymax(int l , int r) {
    	int x , y , z ;
    	split(rt , r , x , z) ;
    	split(x , l - 1 , x , y) ;
    	int res = mx[y] - mn[y] ;
    	rt = merge(merge(x , y) , z) ;
    	return res ;
    }
    int qrymin(int l , int r) {
    	++ l ;
    	int x , y , z ;
    	split(rt , r , x , z) ;
    	split(x , l - 1 , x , y) ;
    	int res = t[y] ;
    	rt = merge(merge(x , y) , z) ;
    	return res ;
    }
    void dfs(int u) {
    	if(ls(u)) dfs(ls(u)) ;
    	out << val[u] << '
    ' ;
    	if(rs(u)) dfs(rs(u)) ;
    }
    signed main() {
    #ifdef _WIN64
    	freopen("testdata.in" , "r" , stdin) ;
    #endif
    	in >> n >> m ;
    	rep(i , 1 , n) in >> a[i] ;
    	rt = newnode(a[1]) ;
    	t[rt] = s[rt] = inf ;
    	rep(i , 2 , n) ins(i - 1 , a[i]) ;
    	rep(i , 1 , m) {
    		string s ;
    		in >> s ;
    		int x , y ;
    		in >> x >> y ;
    		if(s == "max") out << qrymax(x , y) << '
    ' ;
    		if(s == "min") out << qrymin(x , y) << '
    ' ;
    		if(s == "merge") _merge(x , y) ;
    		if(s == "insert") ins(x , y) ;
    	}
    	return out.flush(), 0;
    }
    
  • 相关阅读:
    vector的erase函数
    结构体定义容易混淆的地方
    JavaScript重点知识
    JS中预解析案例分析
    浏览器console控制台不显示编译错误/警告
    强烈推荐一款强大的公式编辑器软件AxMath
    DIV+CSS布局
    CSS-常见属性
    CSS-定义样式表
    CSS-使用CSS样式的方式
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12208778.html
Copyright © 2020-2023  润新知