• P1110 [ZJOI2007]报表统计


    传送门


    emm, 也不用什么权值线段树平衡树啊, set+单点修改不查询的线段树都接近最优解了......
    image
    好想而且很好写, 常数也不大。


    题意

    有n堆数,初始每堆只有一个数, 从左往右排成一列。
    三种操作:

    1.往某一堆的末尾插入一个数
    2.查询相邻两个数的差值(绝对值)的最小值
    3.查询任意两个数的最小差值(绝对值).

    题解

    emm, 由于根本没有删除操作, 那不是好像很好做的样子!
    第三种操作, 每次插入数字的时候, 用set维护一下前驱后继即可。

    考虑第二种操作, 大概是这么一个东西
    image
    每一列表示一堆, 蓝色和红色的边表示相邻的元素, 以及他们的差值
    我们只需要维护它的最小值就行了,

    可以发现蓝色的边是稳定的, 不会消失。 每次插入一个数的时候会和它上面的的那个数产生一条蓝边, 用一个变量维护最小值即可。

    然后红边就不一样了, 它是会消失的。 我插入一个数的时候, 这一堆数原来的红边就消失, 新的红边出现。

    但事实上,每一堆至多有一个红边, 用一个线段树维护它的最小值即可,
    每次插入是时修改一个当前红边的值, 即可
    线段树只需单点修改, 甚至不需要查询(直接用tree[1]即可, 即根节点的权值

    实现

    #include <iostream>
    #include <cstdio>
    #include <set>
    #include <vector> 
    #define l(x) (x*2)
    #define r(x) (x*2+1) 
    using  namespace std;
    
    inline int read(){
    	int num=0, flag=1; char c=getchar();
    	while(!isdigit(c) && c!='-') c=getchar();
    	if(c=='-') flag=-1;
    	while(isdigit(c)) num=num*10+c-'0', c=getchar();
    	return num*flag; 
    }
    
    inline int reads(){
    	int num=0; char c=getchar();
    	while((c<'A' || c>'Z') && c!='_') c=getchar();
    	while((c>='A' && c<='Z') || c=='_') num++, c=getchar();
    	return num;
    }
    
    inline int abs(int x){
    	return x<0?-x:x;
    }
    
    const int N = 600600;
    const int inf = 0x3f3f3f3f;
    int n, m, minv=inf, ming=inf;
    int a[N], las[N];
    set<int> s;
    
    struct segTree{
    	int tree[N<<2];
    	void push_up(int o){
    		tree[o] = min(tree[l(o)], tree[r(o)]);
    	}
    	
    	void build(int o, int l, int r){
    		tree[o] = inf;
    		if(l == r) return ;
    		
    		int mid = (l+r)/2;
    		build(l(o), l, mid);
    		build(r(o), mid+1, r);
    	}
    	
    	void update(int x, int v, int o=1, int l=1, int r=n){
    		if(l==r) {
    			tree[o] = v;
    			return ;
    		}
    		int mid = (l+r)/2;
    		if(x <= mid) update(x, v, l(o), l, mid);
    		else update(x, v, r(o), mid+1, r);
    		push_up(o);
    	} 	
    }t; 
    
    inline void insert(int v){
    	if(minv) {
    		if(s.count(v)) {
    			minv = 0;
    		}else{
    			int res = inf;
    			
    			auto x = s.lower_bound(v);
    			if(x!=s.begin()) x--, res = min(res, abs(*x-v));
    			x = s.upper_bound(v);
    			if(x!=s.end()) res = min(res, abs(*x-v));
    			
    			minv = min(minv, res);
    			
    			s.insert(v);
    		}
    	}
    }
    
    int main(){
    	n=read(), m=read();
    	t.build(1, 1, n);
    	
    	for(int i=1; i<=n; i++){
    		a[i] = las[i] = read(); 
    		insert(a[i]); 
    	}
    	for(int i=1; i<n; i++) t.update(i, abs(las[i] - a[i+1]));
    	
    	while(m--){
    		int type = reads();
    		if(type == 6){
    			int x=read(), v=read();
    			insert(v);
    			
    			ming = min(abs(las[x] - v), ming); 
    			las[x] = v;
    			
    			if(x != n) t.update(x, abs(las[x] - a[x+1]));
    		}else if(type == 7){
    			printf("%d
    ", min(ming, t.tree[1]));
    		}else{
    			printf("%d
    ", minv);
    		}
    	}
    	 
    	return 0;
    } 
    
  • 相关阅读:
    golang中的值传递和引用传递
    链表

    hashtable(哈希表)
    TAO: Facebook’s Distributed Data Store for the Social Graph. 论文阅读笔记(上)
    Skip Lists: A Probabilistic Alternative to Balanced Trees 跳表论文阅读笔记
    【译】如何实现一个现代化电子商城搜索?(一)
    Elasticsearch搜索资料汇总
    Python 按比例获取样本数据或执行任务
    Python 按分类样本数占比生成并随机获取样本数据
  • 原文地址:https://www.cnblogs.com/ltdjcoder/p/15423497.html
Copyright © 2020-2023  润新知