• P4396 [AHOI2013]作业


    P4396 [AHOI2013]作业

    ([l,r]) 区间里在 ([a,b]) 中的数的个数很好求,但是数值个数不太好求
    于是升一维,我们设 (last_i=j) 为第一个使得 (a_j=a_i,j<i)(j),没有就设为 (0)
    然后求数值个数,就是求 (lle x_ile r,ale y_ile b,0le last_ile l-1)(i) 的个数
    于是就是一个三维数点了
    但这样每次 (O(log^3 n)),完全不行,但发现没有修改,于是可以可持久化搞掉一维,也就是求数的个数(二维数点)用可持久化线段树,求数值个数用可持久化树套树
    但又因为不强制在线,所以完全不用真的写一个可持久化树套树,可以离线下来用排序搞掉一维

    主要就是这个升维(处理数值个数)和降维(可持久化)的思路

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<ctime>
    #define reg register
    #define EN puts("")
    inline int read(){
    	register int x=0;register int y=1;
    	register char c=std::getchar();
    	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
    	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
    	return y?x:-x;
    }
    #define N 100006
    int n;
    struct data{
    	int k,a,b,p,o,id;
    }q[2*N];
    int tot;
    inline int cmp(const data &a,const data &b){return a.k<b.k;}
    struct BIT1{
    	#define lowbit(x) (x&(-x))
    	int tree[N];
    	inline int ask(reg int pos){
    		reg int ans=0;
    		for(;pos;pos-=lowbit(pos)) ans+=tree[pos];
    		return ans;
    	}
    	inline void add(reg int pos){
    		for(;pos<=100000;pos+=lowbit(pos)) tree[pos]++;
    	}
    	#undef lowbit
    }Q1;
    struct Segment{
    	struct Node{
    		int ls,rs;
    		int cnt;
    	}p[N*207];
    	int root[N],null;
    	int tot;
    	inline void New(int &a){a=++tot;p[a].ls=p[a].rs=null;p[a].cnt=0;}
    	inline void init(){New(null);for(reg int i=1;i<=100001;i++) New(root[i]);}
    	void add(int &o,int l,int r,int pos){
    		if(o==null) New(o);
    		p[o].cnt++;
    		if(l==r) return;
    		int mid=(l+r)>>1;
    		pos<=mid?add(p[o].ls,l,mid,pos):add(p[o].rs,mid+1,r,pos);
    	}
    	int ask(int o,int l,int r,int ql,int qr){
    		if(o==null) return 0;
    		if(ql<=l&&r<=qr) return p[o].cnt;
    		int mid=(l+r)>>1,ans=0;
    		if(ql<=mid) ans+=ask(p[o].ls,l,mid,ql,qr);
    		if(qr>mid) ans+=ask(p[o].rs,mid+1,r,ql,qr);
    		return ans;
    	}
    }S;
    struct BIT2{
    	#define lowbit(x) (x&(-x))
    	inline int ask(reg int pos,int valL,int valR){
    		reg int ans=0;pos++;
    		for(;pos;pos-=lowbit(pos)) ans+=S.ask(S.root[pos],1,n,valL,valR);
    		return ans;
    	}
    	inline void add(reg int pos,int val){
    		pos++;
    		for(;pos<=100001;pos+=lowbit(pos)) S.add(S.root[pos],1,n,val);
    //		puts("-----------------------------------------");
    	}
    	#undef lowbit
    }Q2;
    int ans1[N],ans2[N];
    int a[N],last[N],tmp[N];
    inline void work(){
    	int pos=1;
    	for(reg int i=1;i<=tot;i++){
    		while(pos<=q[i].k) Q1.add(a[pos]),Q2.add(last[pos],a[pos]),pos++;
    		ans1[q[i].id]+=q[i].o*(Q1.ask(q[i].b)-Q1.ask(q[i].a-1));
    		ans2[q[i].id]+=q[i].o*Q2.ask(q[i].p,q[i].a,q[i].b);
    	}
    }
    int main(){
    //		printf("%lld
    ",sizeof Q1+sizeof Q2+sizeof S);
    	n=read();int m=read();
    	S.init();
    	for(reg int i=1;i<=n;i++){
    		a[i]=read();
    		last[i]=tmp[a[i]];tmp[a[i]]=i;
    	}
    	for(reg int i=1;i<=m;i++){
    		int l=read(),r=read(),a=read(),b=read();
    		q[++tot].k=l-1;q[tot].a=a;q[tot].b=b;q[tot].o=-1;q[tot].id=i;q[tot].p=l-1;
    		q[++tot].k=r;q[tot].a=a;q[tot].b=b;q[tot].o=1;q[tot].id=i;q[tot].p=l-1;
    	}
    	std::sort(q+1,q+1+tot,cmp);
    	work();
    	for(reg int i=1;i<=m;i++) printf("%d %d
    ",ans1[i],ans2[i]);
    	return 0;
    }
    
  • 相关阅读:
    Linix的mysql操作
    Linix安装Mongo
    什么是GitHub
    PHP date, strtotime, mktime处理
    正则表达式及使用
    JavaScript的算法和流程控制总结
    JavaScript的DOM编程总结
    Yii中使用的简单方法
    Mongo数据库的导入导出及使用
    linux-0.11内核 任务的堆栈切换
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/14556092.html
Copyright © 2020-2023  润新知