Atomic Nucleus Investigation 线段树

题目描述

Recently the physicists have been investigating a large family of atomic nucleuses, named “X family”. They have discovered that these atomic nucleuses in X family are quite similar to each other, and can only be distinguished by their weights. And the smaller the weight difference between two kinds of nucleuses is, the more possibly one kind tend to transform to the other.

To research X family in depth, the physicists have devised a series of experiments.

As the most important foundation of these experiments is to control the generation of X family nucleuses, and figure out the instant minimum weight difference among them, the physicists feel like devising a special device which can carry out different kinds of instructions and accomplish the task above. Here are 3 kinds of instructions in desire:

-generate M

Suppose the weights of nucleuses are numbers starting from 1, andM is a positive integer, then the device should produce a nucleus weighted M. If there already exists a nucleus with the same weight, then this instruction should not be taken into account.

- remove M

Suppose M is a positive integer, then the device should remove the existing nucleus weightedM. If no such nucleus exists, the instruction should also be ignored. Please note that a nucleus can exist all the same unless it’s removed by the device.

- query

The device should output the instant minimum weight difference among those existing nucleuses. For example, if there exists 3 nucleuses weighted 1, 7, 10 respectively, then the minimum weight difference is 10-7=3. If there is less than 2 nucleuses with different weight, the query result should be “-1” (without quotes).

Now, your task is to write a program to simulate this special device.

输入格式

Input may contain multiple test cases. The first line is a positive integert, the number of test cases below. For each test case, the input is an instruction sequence. The first line is a single integern, (1 ≤ n ≤ 100000), denoting the number of instructions in this case. And n instructions follow. Each of them is one of the three kinds of instruction as described above, where M is a positive integer no more than 100000.

输出格式

For each test case, each query instruction should correspond to one line of output, containing only one positive integer, which is the corresponding query result. Please output a blank line between test cases.

http://soj.me/show_problem.php?pid=1802

 

 

最经典的线段树题目,建立一个数轴上的线段树,然后维护这个一维数集。

// Problem#: 1802
// Submission#: 1192789
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <cstdio>
#include <algorithm>
using namespace std;

const int N = 131072;
const int INF = 1000000;

struct Node{
    int min;
    int max;
    int min_diff;
    }node[N << 1];

void init(){
    int num = N << 1;
    for (int i =1;i < num;++i){
        node[i].min = INF;
        node[i].max = -INF;
        node[i].min_diff = INF;
        }
    }

inline int query(){
    return node[1].min_diff < N ? node[1].min_diff:-1;
    }
inline int get_left_child(int p){
    return p << 1;
    }
inline int get_right_child(int p){
    return (p << 1)+1;
    }
inline int get_parent(int c){
    return c >> 1;
    }
inline int get_node(int v){
    return v+N-1;
    }
void update(int m){
    int left_child = get_left_child(m),right_child = get_right_child(m);
    node[m].min = min(node[left_child].min,node[right_child].min);
    node[m].max = max(node[left_child].max,node[right_child].max);
    node[m].min_diff = min(node[left_child].min_diff,node[right_child].min_diff);
    node[m].min_diff = min(node[m].min_diff,node[right_child].min-node[left_child].max);
    }

void add(int v){
    int m = get_node(v);
    if ( node[m].min == INF){
        node[m].min = v;
        node[m].max = v;
        do {
            m = get_parent(m);
            update(m);
            } while(m>1);
        }
    }

void remove(int v){
    int m = get_node(v);
    if ( node[m].min == v){
        node[m].min = INF;
        node[m].max = -INF;
        do {
            m = get_parent(m);
            update(m);
            } while(m>1);
        }
    }

int main(){
    int casen;
    scanf("%d",&casen);
    while(--casen>=0){
        init();
        int n;
        scanf("%d",&n);
        for(int i=0; i<n; ++i){
            char cmd[10];
            scanf("%s",cmd);
            if(cmd[0] == 'q'){
                printf("%d\n",query());
                } else {
                    int v;
                    scanf("%d",&v);
                    if(cmd[0] == 'g')
                        add(v);
                    else
                        remove(v);
                }
            }
        if (casen > 0)
            printf("\n");
        }
    return 0;
    }                                 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值