zoukankan      html  css  js  c++  java
  • bzoj 3339 Rmq Problem / mex

    题目

    我的树状数组怎么那么慢啊

    就是一道水题,我们考虑一下对于一个区间([l,r])什么样的数能被计算

    显然需要对于一个(j),需要满足(j<l)(nxt_{j}>r),或者(j>r)(lst_j<l),这样的(a_j)才能被计算到

    发现这不就是一个数点吗,于是我们扫描线加灵活的树状数组就做完了

    代码

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define re register
    #define lb(i) ((i)&(-i))
    #define getchar() (S==T&&(T=(S=BB)+fread(BB,1,1<<15,stdin),S==T)?EOF:*S++)
    char BB[1<<18],*S = BB,*T=BB; 
    const int maxn=200005;
    const int inf=999999999;
    inline int read() {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    struct Ask{int l,r,rk;}q[maxn];
    int n,m,ans,sz;
    inline int min(int a,int b) {return a<b?a:b;}
    int a[maxn],lst[maxn],nxt[maxn],Ans[maxn],ma[maxn],pos[maxn],c[maxn],d[maxn];
    inline int cmp(Ask A,Ask B) {return A.l<B.l;}
    inline int cop(Ask A,Ask B) {return A.r>B.r;}
    inline void change(int x,int val) {for(re int i=x;i;i-=lb(i)) d[i]=min(d[i],val);}
    inline void add(int x,int val) {for(re int i=x;i<=n+1;i+=lb(i)) d[i]=min(d[i],val);}
    inline int ask(int x) {int now=inf,i;for(i=x;i;i-=lb(i)) now=min(now,d[i]);return now;}
    inline int query(int x) {int now=inf,i;x++;for(i=x;i<=n+1;i+=lb(i)) now=min(now,d[i]);return now;}
    inline void work() {
    	ans=inf;
    	if(c[1]!=0) {ans=0;return;}
    	for(re int i=2;i<=sz;i++) {
    		if(c[i]!=c[i-1]+1) {ans=c[i-1]+1;return;} 
    	} 
    	ans=c[sz]+1;
    }
    inline int find(int x) {
    	int l=1,r=sz;
    	while(l<=r) {
    		int mid=l+r>>1;if(c[mid]==x) return mid;
    		if(c[mid]<x) l=mid+1;else r=mid-1;
    	}
    	return 0;
    }
    int main() {
    	n=read(),m=read();
    	for(re int i=1;i<=n;i++) c[i]=a[i]=read();
    	std::sort(c+1,c+n+1);sz=std::unique(c+1,c+n+1)-c-1;
    	for(re int i=n;i;--i) {
    		pos[i]=find(a[i]);
    		nxt[i]=ma[pos[i]],ma[pos[i]]=i;
    	}
    	memset(ma,0,sizeof(ma));
    	for(re int i=1;i<=n;i++) lst[i]=ma[pos[i]],ma[pos[i]]=i;
    	for(re int i=1;i<=m;i++) q[i].l=read(),q[i].r=read(),q[i].rk=i;
    	for(re int i=1;i<=n;i++) if(!nxt[i]) nxt[i]=n+1;
    	std::sort(q+1,q+m+1,cmp);
    	for(re int i=1;i<=n+1;i++) d[i]=inf;
    	for(re int i=1;i<=m;i++) Ans[i]=inf;
    	int now=1;
    	for(re int i=1;i<=m;i++) {
    		while(now<q[i].l) {change(nxt[now],a[now]);now++;}
    		Ans[q[i].rk]=min(Ans[q[i].rk],query(q[i].r));
    	}
    	for(re int i=1;i<=n;i++) d[i]=inf;
    	std::sort(q+1,q+m+1,cop);
    	now=n;
    	for(re int i=1;i<=m;i++) {
    		while(now>q[i].r) {add(lst[now]+1,a[now]);now--;}
    		Ans[q[i].rk]=min(Ans[q[i].rk],ask(q[i].l));
    	}
    	work();
    	for(re int i=1;i<=m;i++) printf("%d
    ",min(Ans[i],ans));
    	return 0;
    }
    
  • 相关阅读:
    Golang学习开篇——Go语言优势
    Ubuntu —— 查看和开放端口
    mysql——sql语句
    python模块——xlwt
    字典容器类型使用之坑
    pandas——将sql查询结果,分几部分存入excel
    pandas 点击 excel 表格数据,跳转到 sheet2
    datetime——计算前一天的这个时间 坑
    报错总结
    nginx——部署前端
  • 原文地址:https://www.cnblogs.com/asuldb/p/10543051.html
Copyright © 2011-2022 走看看