题面
首先,由于本人太菜,不会莫队,所以先采用主席树的做法;
离散化是必须环节,否则动态开点线段数都救不了你;
我们对于每个元素i,插入到1~(i-1)的主席树中,第i颗线段树(权值线段树)对于一个区间[l,r]维护的便是原序列1~i中的所有属于[l,r]的元素出现的最后位置的最小值;
当我们查询[x,y]时,我们查询第y颗线段树,找到第一个位置使得(出现的最后位置的最小值)比(x)要小;
然后恢复离散化之前的数值,然后输出;
#include#define inc(i,a,b) for(register int i=a;i<=b;i++) using namespace std; int n,m; int a[300010]; int tot; class node{ public: int lson,rson; int last; }tree[6000010]; int lisan,tt[400010],root[300010]; int change(int pre,int l,int r,int goal,int v) { int now=++tot; tree[now].lson=tree[pre].lson; tree[now].rson=tree[pre].rson; if(l==r){ tree[tot].last=v; return now; } int mid=(l+r)/2; if(goal<=mid) tree[now].lson=change(tree[pre].lson,l,mid,goal,v); else tree[now].rson=change(tree[pre].rson,mid+1,r,goal,v); tree[now].last=min(tree[tree[now].lson].last,tree[tree[now].rson].last); return now; } int query(int now,int l,int r,int goal) { if(l==r) return tt[l]; int mid=(l+r)/2; if(tree[tree[now].lson].last>=goal) return query(tree[now].rson,mid+1,r,goal); else return query(tree[now].lson,l,mid,goal); } int main(){ scanf("%d%d",&n,&m); tt[++lisan]=0; inc(i,1,n){ scanf("%d",&a[i]); tt[++lisan]=a[i]; tt[++lisan]=a[i]+1; } sort(tt+1,tt+1+lisan); lisan=unique(tt+1,tt+1+lisan)-tt-1; inc(i,1,n){ a[i]=lower_bound(tt+1,tt+1+lisan,a[i])-tt; root[i]=tot+1; change(root[i-1],1,lisan,a[i],i); } inc(i,1,m){ int x,y; scanf("%d%d",&x,&y); printf("%d\n",query(root[y],1,lisan,x)); } }
或许以后会更新一篇莫队的做法