zoukankan      html  css  js  c++  java
  • P2234 [HNOI2002]营业额统计

    题面传送门

    题意:对于N天的营业额,你需要求出每天营业额与当天前的营业额差值的最小值的和。

    思路:感觉挺裸的SBT,对于每天的营业额x,插值,求x与x的前驱的差值d1,求x的后继与x的差值d2(ps:这里的前驱后继的可以等于x),用一个treap就可以过了。


    Code:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    //Mystery_Sky
    //
    #define M 1000100
    #define INF 0x3f3f3f3f
    #define ll long long
    inline int read()
    {
    	int x = 0,f=1; char c=getchar();
    	while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
    	return x*f;
    }
    struct Treap{
    	int size, cnt;
    	int l, r;
    	int dat, val;
    }a[M];
    
    int tot, root, n, ans;
    
    inline int New(int val)
    {
    	a[++tot].val = val;
    	a[tot].dat = rand();
    	a[tot].cnt = a[tot].size = 1;
    	return tot;
    }
    
    inline void update(int p)
    {
    	a[p].size = a[a[p].l].size + a[a[p].r].size + a[p].cnt;
    }
    
    inline void build()
    {
    	root = New(-INF);
    	a[root].r = New(INF);
    	update(root);
    }
    
    inline void right_Rotate(int &p)
    {
    	int k = a[p].l;
    	a[p].l = a[k].r, a[k].r = p, p = k;
    	update(a[p].r);
    	update(p);
    }
    
    inline void left_Rotate(int &p)
    {
    	int k = a[p].r;
    	a[p].r = a[k].l, a[k].l = p, p = k;
    	update(a[p].l);
    	update(p);
    }
    
    void insert(int &p, int val)
    {
    	if(!p) {
    		p = New(val);
    		return;
    	}
    	if(val == a[p].val) {
    		a[p].cnt++;
    		update(p);
    		return;	
    	}
    	else if(val < a[p].val) {
    		insert(a[p].l, val);
    		if(a[p].dat < a[a[p].l].dat) right_Rotate(p);
    	}
    	else {
    		insert(a[p].r, val);
    		if(a[p].dat > a[a[p].r].dat) left_Rotate(p);
    	}
    	update(p);
    }
    
    int query_pre(int val)
    {
    	int ans = a[root].val;
    	int p = root;
    	while(p) {
    		if(a[p].val == val && a[p].cnt > 1) return val;
    		if(a[p].val < val) ans = a[p].val, p = a[p].r;
    		else p = a[p].l;			
    	}
    	return ans;
    }
    
    inline int query_next(int val)
    {
    	int ans = a[root].val;
    	int p = root;
    	while(p) {
    		if(a[p].val == val && a[p].cnt > 1) return val;
    		if(a[p].val > val) ans = a[p].val, p = a[p].l;
    		else p = a[p].r;
    	}
    	return ans;
    }
    
    int main() {
    	n = read();
    	build();
    	for(int i = 1; i <= n; i++) {
    		int x = read();
    		if(i == 1) ans += x, insert(root, x);
    		else {
    			insert(root, x);
    			int d1 = abs(x - query_pre(x));
    			int d2 = abs(query_next(x) - x);
    			//printf("%d %d
    ", d1, d2);
    			ans += min(d1, d2);
    		}
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    Windows批处理方式实现MySQL定期自动备份多个数据库
    MySQL数据库中库、表名、字段的大小写问题
    使用modbus4j通过串口解析modbus协议(java)
    mybatis —— 动态sql之if条件判断各种使用方式
    Mysql 获取表的comment 字段
    [转载]如何判断数据库,表或字段是否存在
    设计模式目录
    图片上传及访问
    实现第一个API
    ListView 源码解析
  • 原文地址:https://www.cnblogs.com/Benjamin-cpp/p/11515448.html
Copyright © 2011-2022 走看看