zoukankan      html  css  js  c++  java
  • 【洛谷P1110】报表统计【平衡树】【堆】

    题目大意:

    题目链接:https://www.luogu.org/problem/P1110

    在最开始的时候,有一个长度为NN的整数序列,并且有以下三种操作:

    • INSERT i kINSERT i k:在原数列的第ii个元素后面添加一个新元素kk;如果原数列的第ii个元素已经添加了若干元素,则添加在这些元素的最后
    • MIN_GAPMIN\_GAP:查询相邻两个元素的之间差值(绝对值)的最小值
    • MIN_SORT_GAPMIN\_SORT\_GAP:查询所有元素中最接近的两个元素的差值(绝对值)

    思路:

    首先操作三是很简单的,我们只要写一棵平衡树,维护每一个数字的前驱后继,每次插入一个数就判断它与它前驱后继的差值是否小于minnminn。如果小于就更新。
    对于第二问,定义last[i]last[i]表示原序列第ii个数字后面插入的最后一个数字,如果我们在原序列第ii个数字后面插入xx,那么会受影响的只有abs(a[i+1]last[i])abs(a[i+1]-last[i])。因为在last[i]last[i]a[i+1]a[i+1]中插入了一个新的数字。
    同时我们还加入了两个新的数字abs(xlast[i])abs(x-last[i])abs(xa[i+1])abs(x-a[i+1])。而我们要求这些数字的最小值,所以我们可以将所有这些数字插入一个小跟堆中。每次去最小值。
    那么如果最小值本来应该删除的话怎么办呢?我们可以再建一个小根堆,把要删除的数字插入小根堆中。如果此时的最小值和要删除数字的最小值一样,那么这个最小值就是要删除的,两个堆都弹出即可。
    时间复杂度O(mlog(n+m))O(mlog (n+m))


    代码:

    #include <queue>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int N=1000010,Inf=1e9;
    int n,m,root,minn,a[N],last[N];
    char ch[30];
    priority_queue<int> q,p;
    
    struct Treenode
    {
    	int lc,rc,val,cnt,dat;
    };
    
    struct Treap
    {
    	Treenode tree[N];
    	int tot;
    	
    	int New(int val)
    	{
    		tree[++tot].val=val;
    		tree[tot].dat=rand();
    		tree[tot].cnt=1;
    		return tot;
    	}
    	
    	void build()
    	{
    		root=New(-Inf);
    		tree[root].rc=New(Inf);
    	}
    	
    	void zig(int &x)
    	{
    		int y=tree[x].lc;
    		tree[x].lc=tree[y].rc; tree[y].rc=x; x=y;
    	}
    	
    	void zag(int &x)
    	{
    		int y=tree[x].rc;
    		tree[x].rc=tree[y].lc; tree[y].lc=x; x=y;
    	}
    	
    	void insert(int &x,int val)
    	{
    		if (!x)
    		{
    			x=New(val);
    			return;
    		}
    		if (tree[x].val==val)
    		{
    			tree[x].cnt++;
    			return;
    		}
    		if (val<tree[x].val)
    		{
    			insert(tree[x].lc,val);
    			if (tree[x].dat<tree[tree[x].lc].dat) zig(x);
    		}
    		else
    		{
    			insert(tree[x].rc,val);
    			if (tree[x].dat<tree[tree[x].rc].dat) zag(x);
    		}
    	}
    	
    	int pre(int x,int val)
    	{
    		if (!x) return -Inf;
    		if (tree[x].val<val) return max(tree[x].val,pre(tree[x].rc,val));
    			else return pre(tree[x].lc,val);
    	}
    	
    	int next(int x,int val)
    	{
    		if (!x) return Inf;
    		if (tree[x].val>val) return min(tree[x].val,next(tree[x].lc,val));
    			else return next(tree[x].rc,val);
    	}
    	
    	int cnt(int x,int val)
    	{
    		if (!x) return 0;
    		if (val==tree[x].val) return tree[x].cnt;
    		if (val<tree[x].val) return cnt(tree[x].lc,val);
    			else return cnt(tree[x].rc,val);
    	}
    }Treap;
    
    int main()
    {
    	srand(23333);
    	Treap.build();
    	scanf("%d%d",&n,&m);
    	minn=Inf;
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		last[i]=a[i];
    		Treap.insert(root,a[i]);
    		if (i>1) q.push(-abs(a[i]-a[i-1]));
    		if (Treap.cnt(root,a[i])>1) minn=0;
    		if (minn)
    		{
    			int ans1=a[i]-Treap.pre(root,a[i]),ans2=Treap.next(root,a[i])-a[i];
    			minn=min(minn,min(ans1,ans2));
    		}
    	}
    	while (m--)
    	{
    		scanf("%s",ch+1);
    		if (ch[1]=='I')
    		{
    			int x,y;
    			scanf("%d%d",&x,&y);
    			Treap.insert(root,y);
    			q.push(-abs(y-last[x]));
    			if (x<n)
    			{
    				q.push(-abs(y-a[x+1]));
    				p.push(-abs(last[x]-a[x+1]));
    			}
    			if (Treap.cnt(root,y)>1) minn=0;
    			if (minn)
    			{
    				int ans1=y-Treap.pre(root,y),ans2=Treap.next(root,y)-y;
    				minn=min(minn,min(ans1,ans2));
    			}
    			last[x]=y;
    		}
    		else if (ch[5]=='S') printf("%d
    ",minn);
    		else
    		{
    			while (q.size() && p.size() && q.top()==p.top())
    				q.pop(),p.pop();
    			printf("%d
    ",-q.top());
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    vue-cli element axios sass 安装
    Rem-- ui图与适配手机的px换算
    REM
    Canvas画半圆扇形统计图
    在vue中安装SASS
    在vue中引用.SCSS的公用文件
    Echart--折线图手柄触发事件
    vue 脚手架webpack打包后,解决能看到vue源码的问题
    js 函数 /变量/ 以及函数中形参的预解析的顺序
    【算法日记】4.递归和快速排序
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998025.html
Copyright © 2011-2022 走看看