• BZOJ3489: A simple rmq problem


    设$i$的前驱为$p_i$,后继为$q_i$,把询问看成点$(L,R)$,有贡献的$i$满足$Lin(p_i,i]$且$Rin[i,q_i)$,询问的就是覆盖这个点的矩形的最大值。那么可以用可持久化树套堆,插入矩形时一维可持久化,一维区间插入,用堆维护最大值。注意这里的“可持久化堆”只需要查询历史,因此只需要把最大值记下来就好了。

    #include<algorithm>
    #include<cstdio>
    #include<queue>
    #define I (J+1)
    #define J (i+j>>1)
    #define P (k<<1)
    #define S (P^1)
    using namespace std;
    const int N=1e5+5;
    int n,m;
    typedef int arr[N];
    arr p,q,f,a;
    struct heap{
    	priority_queue<int>s,t;
    	void ins(int j){
    		s.push(j);
    	}
    	void del(int j){
    		t.push(j);
    	}
    	int top(){
    		while(t.size()&&s.top()==t.top())
    			s.pop(),t.pop();
    		return s.size()?s.top():0;
    	}
    }c[1<<18];
    typedef struct node*ptr;
    struct node{
    	ptr i,j;
    	int s;
    }e[N*136];
    ptr z=e+1,r[N];
    int eval(int v,ptr s,int i=1,int j=n){
    	if(i==j)
    		return s->s;
    	return max(s->s,v<I?eval(v,s->i,i,J):eval(v,s->j,I,j));
    }
    struct info{
    	void(heap::*foo)(int);
    	int f,s,t;
    };
    void vary(info f,ptr&s,int i=1,int j=n,int k=1){
    	s=&(*z++=*s);
    	if(f.s<=i&&j<=f.t){
    		(c[k].*f.foo)(f.f);
    		s->s=c[k].top();
    	}
    	else{
    		if(f.s<I)
    			vary(f,s->i,i,J,P);
    		if(f.t>J)
    			vary(f,s->j,I,j,S);
    	}
    }
    struct edge{
    	edge*s;
    	info f;
    }e2[N*2];
    edge*z2=e2,*y[N];
    int main(){
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i){
    		scanf("%d",a+i);
    		p[i]=f[a[i]],f[a[i]]=i;
    	}
    	fill(f+1,f+n+1,n+1);
    	for(int i=n;i;--i)
    		q[i]=f[a[i]],f[a[i]]=i;
    	for(int i=n;i;--i){
    		int s=p[i]+1,t=i+1;
    		edge u={
    			y[s],&heap::ins,a[i],i,q[i]-1
    		};
    		edge v={
    			y[t],&heap::del,a[i],i,q[i]-1
    		};
    		*(y[s]=z2++)=u;
    		*(y[t]=z2++)=v;
    	}
    	*(*r=e)=(node){
    		e,e
    	};
    	for(int i=1;i<=n;++i){
    		r[i]=r[i-1];
    		for(edge*j=y[i];j;j=j->s)
    			vary(j->f,r[i]);
    	}
    	int k=0,s,t;
    	while(m--){
    		scanf("%d%d",&s,&t);
    		if((s=(s+k)%n+1)>(t=(t+k)%n+1))
    			swap(s,t);
    		printf("%d
    ",k=eval(t,r[s]));
    	}
    }
    
  • 相关阅读:
    Linux 6.2 配置NTP服务
    配置SSH三大框架报错
    Linux 6.2 源码安装和配置Puppet
    PGA 内存管理
    调整linux系统时间和时区与Internet时间同步
    Java 文件分块上传客户端和服务器端源代码
    Java 文件分块上传服务器端源代码
    Java 服务器端支持断点续传的源代码【支持快车、迅雷】(仅支持 HTTP 协议)
    bbed使用
    OracleDatabase 11g安装bbed
  • 原文地址:https://www.cnblogs.com/f321dd/p/5995255.html
Copyright © 2020-2023  润新知