zoukankan      html  css  js  c++  java
  • [BZOJ3236][AHOI2013]作业:树套树/莫队+分块

    分析

    第一问随便搞,直接说第二问。

    令原数列为(seq)(pre_i)(seq_i)这个值上一个出现的位置,于是可以简化询问条件为:

    1. (l leq i leq r)

    2. (a leq seq_i leq b)

    3. (pre_i < l)

    这是一个显然的三维数点问题。发现第三维(pre_i)只有最大值的限制,所以我们可以把所有询问按(l)升序排序,所有点按(pre_i)升序排序,用一个指针从左往右扫所有询问,然后不断向数据结构插入符合第三维要求的点,剩下的两维树状数组套权值线段树解决。

    然后就被卡空间了。

    然后题解告诉我们可以莫队+分块解决。

    (这里因为修改次数远大于询问次数所以使用分块而非树状数组。)

    (FAQ)

    代码

    树套树(MLE)

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <cctype>
    #include <algorithm>
    #define lowbit(x) ((x)&(-(x)))
    #define rin(i,a,b) for(int i=(a);i<=(b);i++)
    #define rec(i,a,b) for(int i=(a);i>=(b);i--)
    #define trav(i,x) for(int i=head[(x)];i;i=e[i].nxt)
    using std::cin;
    using std::cout;
    using std::endl;
    typedef long long LL;
    
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    
    const int MAXN=100005;
    const int MAXM=1000005;
    int n,m,siz,tot,a[MAXN],b[MAXN],pre[MAXN],las[MAXN];
    int ans1[MAXM],ans2[MAXM];
    int loc,ql,qr,root[MAXN],lc[MAXN*__],rc[MAXN*__],sum[MAXN*__];//FAQ
    
    struct Po{
    	int pos,val,pre;
    	inline friend bool operator < (Po x,Po y){return x.pre<y.pre;}
    }p[MAXN];
    
    struct Qu{
    	int l,r,a,b,id;
    	inline friend bool operator < (Qu x,Qu y){return x.l<y.l;}
    }q[MAXM];
    
    #define mid ((l+r)>>1)
    int upd(int pre,int l,int r){
    	int o=++tot;lc[o]=lc[pre],rc[o]=rc[pre],sum[o]=sum[pre]+1;
    	if(l==r) return o;
    	if(loc<=mid) lc[o]=upd(lc[pre],l,mid);
    	else rc[o]=upd(rc[pre],mid+1,r);
    	return o;
    }
    
    int query(int o,int l,int r){
    	if(ql>qr) return 0;
    	if(ql<=l&&r<=qr) return sum[o];
    	int ret=0;
    	if(mid>=ql) ret+=query(lc[o],l,mid);
    	if(mid<qr) ret+=query(rc[o],mid+1,r);
    	return ret;
    }
    
    int query(int u,int v,int l,int r){
    	if(ql>qr) return 0;
    	if(ql<=l&&r<=qr) return sum[v]-sum[u];
    	int ret=0;
    	if(mid>=ql) ret+=query(lc[u],lc[v],l,mid);
    	if(mid<qr) ret+=query(rc[u],rc[v],mid+1,r);
    	return ret;
    }
    #undef mid
    
    inline void Add(int pos,int val){
    	loc=val;
    	for(int i=pos;i<=n;i+=lowbit(i)) root[i]=upd(root[i],1,siz);
    }
    
    inline int Ask(int x){
    	if(ql>qr) return 0;
    	int ret=0;
    	for(int i=x;i;i-=lowbit(i)) ret+=query(root[i],1,siz);
    	return ret;
    }
    
    inline int Ask(int l,int r,int lval,int rval){
    	ql=lval,qr=rval;
    	if(ql>qr) return 0;
    	return Ask(r)-Ask(l-1);
    }
    
    int main(){
    	n=read(),m=read();
    	rin(i,1,n) b[i]=a[i]=read();
    	std::sort(b+1,b+n+1);
    	siz=std::unique(b+1,b+n+1)-b-1;
    	rin(i,1,n) a[i]=std::lower_bound(b+1,b+siz+1,a[i])-b;
    	rin(i,1,n){pre[i]=las[a[i]];las[a[i]]=i;p[i]=(Po){i,a[i],pre[i]};}
    	rin(i,1,m){q[i].l=read(),q[i].r=read(),q[i].a=std::lower_bound(b+1,b+siz+1,read())-b,q[i].b=std::upper_bound(b+1,b+siz+1,read())-b-1,q[i].id=i;}
    	rin(i,1,n){loc=a[i];root[i]=upd(root[i-1],1,siz);}
    	rin(i,1,m){ql=q[i].a,qr=q[i].b;ans1[i]=query(root[q[i].l-1],root[q[i].r],1,siz);}
    	tot=0;memset(root,0,sizeof root);std::sort(p+1,p+n+1);std::sort(q+1,q+m+1);
    	int pptr=1,qptr=1;
    	while(pptr<=n&&!p[pptr].pre){Add(p[pptr].pos,p[pptr].val);pptr++;}
    	rin(i,1,n){
    		while(qptr<=m&&q[qptr].l==i){ans2[q[qptr].id]=Ask(q[qptr].l,q[qptr].r,q[qptr].a,q[qptr].b);qptr++;}
    		while(pptr<=n&&p[pptr].pre==i){Add(p[pptr].pos,p[pptr].val);pptr++;}
    	}
    	rin(i,1,m) printf("%d %d
    ",ans1[i],ans2[i]);
    	return 0;
    }
    

    莫队+分块

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <cctype>
    #include <algorithm>
    #define rin(i,a,b) for(int i=(a);i<=(b);i++)
    #define rec(i,a,b) for(int i=(a);i>=(b);i--)
    #define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
    using std::cin;
    using std::cout;
    using std::endl;
    typedef long long LL;
    
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    
    const int MAXN=100005;
    const int MAXM=1000005;
    const int SIZE=345;
    
    int n,m,siz,ret1,ret2,a[MAXN],b[MAXN],blg[MAXN],cnt[MAXN],sum1[SIZE],sum2[SIZE],ans1[MAXM],ans2[MAXM];
    struct Qu{
    	int l,r,lk,a,b,id;
    	inline friend bool operator < (Qu x,Qu y){
    		if(x.lk!=y.lk) return x.lk<y.lk;
    		if(x.lk&1) return x.r<y.r;
    		else return x.r>y.r;
    	}
    }q[MAXM];
    
    inline void query(int l,int r){
    	ret1=ret2=0;
    	rin(i,blg[l]+1,blg[r]-1) ret1+=sum1[i],ret2+=sum2[i];
    	int lim=std::min(blg[l]*SIZE,r);rin(i,l,lim) ret1+=cnt[i],ret2+=(cnt[i]>0);
    	if(blg[l]!=blg[r]) rin(i,(blg[r]-1)*SIZE+1,r) ret1+=cnt[i],ret2+=(cnt[i]>0);
    }
    
    int main(){
    	n=read(),m=read();
    	rin(i,1,n) a[i]=b[i]=read();
    	std::sort(b+1,b+n+1);siz=std::unique(b+1,b+n+1)-b-1;
    	rin(i,1,n){a[i]=std::lower_bound(b+1,b+siz+1,a[i])-b;blg[i]=(i-1)/SIZE+1;};
    	rin(i,1,m){q[i].l=read(),q[i].r=read(),q[i].a=std::lower_bound(b+1,b+siz+1,read())-b,q[i].b=std::upper_bound(b+1,b+siz+1,read())-b-1,q[i].lk=(q[i].l-1)/SIZE+1;q[i].id=i;}
    	std::sort(q+1,q+m+1);
    	int l=1,r=0;
    	rin(i,1,m){
    		if(q[i].a>q[i].b) continue;
    		while(l>q[i].l){l--;cnt[a[l]]++;sum1[blg[a[l]]]++;if(cnt[a[l]]==1)sum2[blg[a[l]]]++;}
    		while(r<q[i].r){r++;cnt[a[r]]++;sum1[blg[a[r]]]++;if(cnt[a[r]]==1)sum2[blg[a[r]]]++;}
    		while(l<q[i].l){cnt[a[l]]--;sum1[blg[a[l]]]--;if(cnt[a[l]]==0)sum2[blg[a[l]]]--;l++;}
    		while(r>q[i].r){cnt[a[r]]--;sum1[blg[a[r]]]--;if(cnt[a[r]]==0)sum2[blg[a[r]]]--;r--;}
    		query(q[i].a,q[i].b);ans1[q[i].id]=ret1;ans2[q[i].id]=ret2;
    	}
    	rin(i,1,m) printf("%d %d
    ",ans1[i],ans2[i]);
    	return 0;
    }
    
  • 相关阅读:
    学习进度笔记01
    进度报表十一
    进度报表十
    进度日报九
    进度日报八
    进度日报七
    第七周总结
    进度报表六
    第一阶段冲刺6
    第一阶段冲刺5
  • 原文地址:https://www.cnblogs.com/ErkkiErkko/p/10107610.html
Copyright © 2011-2022 走看看