zoukankan      html  css  js  c++  java
  • CF GYM. 102861M. Machine Gun(主席树)

    题目链接


    简直是傻了做的时候连主席树都不会用了

    容易发现,合法的点((x,y))若满足询问((qx,qy)),则需满足(2y-xleq 2qy-qx, 2y+xgeq 2qy+qx),将点((x,y))变为((2y-x,2y+x)),就是一个二维偏序。
    强制在线,最简单的办法就是线段树套线段树(TLE on #2),或是按(x)排序后对(y)轴建主席树。
    还有一个在线方法是区间树(std,但是我的TLE on #5/whl,是我太菜了):换一下表示方式,题意等价于求与([2qy+qx,2qy-qx])相交的所有区间,用线段树+区间树可以实现(纯区间树应该做不了吧,所以常数很大)。区间树见这儿,很裸。

    记一下主席树的细节:纵坐标(y_i)((n+1) imes y_i+i)进行储存和离散化,这样一是没有可持久化要存(vector)的问题,二是主席树(Query)出来的答案就是按标号排好序的(不需再排序)。
    为了方便可以用((y_i<<18)+i),这样某个(y)位置的编号就是(y&((1<<18)-1))。(最好用(2y+x)作为(y)(y)做编号时为正数?)


    主席树:

    //296ms	19600KB
    #include <bits/stdc++.h>
    #define pc putchar
    #define gc() getchar()
    #define pb emplace_back
    #define mod 1000000007
    typedef long long LL;
    const int N=1e5+5,M=(1<<18)-1;
    
    int root[N],cnt,Ans[N];
    LL X[N],Y[N],pw[N];
    struct Node
    {
    	LL x,y;
    	bool operator <(const Node &a)const
    	{
    		return x<a.x;
    	}
    }A[N];
    struct President_Tree
    {
    	#define S N*19
    	#define ls son[x][0]
    	#define rs son[x][1]
    	#define lson ls,son[y][0],l,m
    	#define rson rs,son[y][1],m+1,r
    	int tot,son[S][2];
    	#undef S
    	void Insert(int &x,int y,int l,int r,int p)
    	{
    		x=++tot;
    		if(l==r) return;
    		int m=l+r>>1;
    		p<=m?(rs=son[y][1],Insert(lson,p)):(ls=son[y][0],Insert(rson,p));
    	}
    	void Query(int x,int l,int r,int p)//p~N
    	{
    		if(!x) return;
    		if(l==r) {Ans[++cnt]=Y[l]&M; return;}
    		int m=l+r>>1;
    		p<=m && (Query(ls,l,m,p),0);
    		Query(rs,m+1,r,p);
    	}
    }T;
    
    inline int read()
    {
    	int now=0,f=1; char c=gc();
    	for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
    	for(;isdigit(c);now=now*10+c-48,c=gc());
    	return now*f;
    }
    int Find(int r,LL v)//the first num satisfying >=v
    {
    	int l=1,mid;
    	while(l<r)
    		if(Y[mid=l+r>>1]<v) l=mid+1;
    		else r=mid;
    	return l;
    }
    int Find2(int r,LL v)//the first num satisfying <=v
    {
    	if(X[1]>v) return 0;
    	int l=1,mid,ans=0;
    	while(l<=r)
    		if(X[mid=l+r>>1]<=v) l=mid+1,ans=mid;
    		else r=mid-1;
    	return ans;
    }
    
    int main()
    {
    	int n=read(),Q=read();
    	pw[0]=1;
    	for(int i=1; i<=n; ++i) pw[i]=pw[i-1]*5782344%mod;
    	for(int i=1; i<=n; ++i)
    	{
    		LL x=read(),y=read();
    		A[i].x=2*y-x, Y[i]=A[i].y=((2*y+x)<<18)+i;
    	}
    
    	std::sort(A+1,A+1+n), std::sort(Y+1,Y+1+n);
    	for(int i=1; i<=n; ++i) X[i]=A[i].x;
    	for(int i=1; i<=n; ++i) T.Insert(root[i],root[i-1],1,n,Find(n,A[i].y));
    
    	for(int p=0; Q--; )
    	{
    		LL x=-1-((p+read())%mod),y=(p+read())%mod;
    		if(2*y+x>Y[n]) {printf("%d
    ",p=0); continue;}
    
    		int R1=Find2(n,2*y-x),L2=Find(n,(2*y+x)<<18);
    		cnt=0, T.Query(root[R1],1,n,L2);
    
    		LL res=0;
    		std::sort(Ans+1,Ans+1+cnt);
    		LL *pw_=pw;
    		for(int *a=Ans+1,*lim=Ans+cnt+1; a!=lim; ++a,++pw_) res+=(*a)*(*pw_)%mod;
    		p=(int)(res%mod), printf("%d
    ",p);
    	}
    
    	return 0;
    }
    

    区间树:

    /*
    TLE on #5
    */
    #include <bits/stdc++.h>
    #define pc putchar
    #define gc() getchar()
    #define pb emplace_back
    #define mod 1000000007
    #define Vec std::vector<Node>
    typedef long long LL;
    const int N=(1e5+5)*2;//*2
    
    #define De 0
    struct Node
    {
    	int l,r,id;
    	bool operator <(const Node &x)const
    	{
    		return l!=x.l?l<x.l:r<x.r;
    	}
    	bool operator <=(const Node &x)const
    	{
    		id<x.id;
    	}
    	bool operator !=(const Node &x)const
    	{
    		return id!=x.id;
    	}
    	void P() {printf("%d~%d %d
    ",l,r,id);}
    }node[N];
    std::vector<int> Ans,Ans2;
    
    //inline bool Cmp(const Node &a,const Node &b)
    //{
    //	return a.l!=b.l?a.l<b.l:a.r<b.r;
    //}
    
    inline void Merge(std::vector<int> &rt,std::vector<int> &a,std::vector<int> &b)
    {
    	std::vector<int> tmp;
    	auto l=a.begin(),le=a.end(),r=b.begin(),re=b.end();
    	while(l!=le&&r!=re)
    		if(*l<*r) tmp.pb(*l++);
    		else if(*l>*r) tmp.pb(*r++);
    		else tmp.pb(*l++), r++;
    	while(l!=le) tmp.pb(*l++);
    	while(r!=re) tmp.pb(*r++);
    	int las=0; std::vector<int>().swap(rt);//先用完a,b再清空!
    	for(auto i:tmp)
    		if(i!=las) rt.pb(i), las=i;
    }
    struct Segment_Tree
    {
    	#define S N<<2
    	#define ls rt<<1
    	#define rs rt<<1|1
    	#define lson l,m,ls
    	#define rson m+1,r,rs
    	int son[S][2];
    	std::vector<int> vec[S];
    	#undef S
    	void Insert(int l,int r,int rt,int p,int id)
    	{
    		if(l==r) {vec[rt].pb(id); return;} 
    		int m=l+r>>1;
    		p<=m?Insert(lson,p,id):Insert(rson,p,id);
    	}
    	void Maintain(int l,int r,int rt)
    	{
    		if(l==r) return;
    		int m=l+r>>1;
    		Maintain(lson), Maintain(rson), Merge(vec[rt],vec[ls],vec[rs]);
    	}
    	void Query(int l,int r,int rt,int L,int R)
    	{
    		if(L<=l && r<=R) {Merge(Ans,Ans,vec[rt]); return;}
    		int m=l+r>>1;
    		if(L<=m) Query(lson,L,R);
    		if(m<R) Query(rson,L,R);
    	}
    	#undef ls
    	#undef rs
    	#undef lson
    	#undef rson
    }ST;
    struct Interval_Tree
    {
    	#define S N*19//N<<2
    	#define ls son[rt][0]
    	#define rs son[rt][1]
    	int tot,A[N<<1],son[S][2],center[S];
    	Vec Sa[S],Sb[S];
    	#undef S
    	void Build(int &rt,Vec &va,Vec &vb)
    	{
    		int t=va.size();
    		if(!t) {rt=0; return;}
    		int cnt=0; !rt&&(rt=++tot);
    		for(auto i:va) A[++cnt]=i.l, A[++cnt]=i.r;
    		std::nth_element(A+1,A+t,A+1+cnt);//O(n)找中位数 
    		int xc=A[t]; center[rt]=xc;
    //		if(De)
    //		{
    //			printf("
    rt:%d
    A:",rt);
    //			for(auto i:va) i.P();
    //			printf("B:"); for(auto i:vb) i.P();
    //			printf("center:%d
    ",xc);
    //		}
    		Vec val,vbl,var,vbr;
    		for(auto i:va)
    			if(i.r<xc) val.pb(i);
    			else if(i.l>xc) var.pb(i);
    			else Sa[rt].pb(i);
    		for(auto i:vb)
    			if(i.r<xc) vbl.pb(i);
    			else if(i.l>xc) vbr.pb(i);
    			else Sb[rt].pb(i);
    		Build(ls,val,vbl), Build(rs,var,vbr);
    	}
    	#define Update() std::sort(tmp.begin(),tmp.end()), Merge(Ans2,Ans2,tmp)
    //	#define Update() rt
    	void Query(int rt,int p)
    	{
    		if(!rt) return;
    		std::vector<int> tmp;
    		if(p==center[rt])
    		{
    			for(auto i:Sa[rt]) tmp.pb(i.id);
    			Update();
    		}
    		else if(p<center[rt])
    		{
    			for(auto i:Sa[rt])
    				if(i.l<=p) tmp.pb(i.id); else break;
    			Update(), Query(ls,p);
    		}
    		else
    		{
    			for(auto i:Sb[rt])
    				if(i.r>=p) tmp.pb(i.id); else break;
    			Update(), Query(rs,p);
    		}
    	}
    }IT;
    struct Array
    {
    	int cnt;
    	LL A[N],B[N],Ref[N];
    	int Find(LL v)
    	{
    		if(Ref[cnt]<v) return cnt+1;
    		int l=1,r=cnt,mid;
    		while(l<r)
    			if(Ref[mid=l+r>>1]<v) l=mid+1;
    			else r=mid;
    		return l;
    	}
    	int Find2(LL v)
    	{
    		if(Ref[1]>v) return 0;
    		int l=1,r=cnt,mid,ans=0;
    		while(l<=r)
    			if(Ref[mid=l+r>>1]<=v) l=mid+1,ans=mid;
    			else r=mid-1;
    		return ans;
    	}
    	void Discrete(const int n)
    	{
    		const int m=n<<1;
    		for(int i=1; i<=n; ++i) Ref[(i<<1)-1]=A[i], Ref[i<<1]=B[i];
    		std::sort(Ref+1,Ref+1+m);
    		cnt=1;
    		for(int i=2; i<=m; ++i) if(Ref[i]!=Ref[i-1]) Ref[++cnt]=Ref[i];
    		for(int i=1; i<=n; ++i) A[i]=Find(A[i]), B[i]=Find(B[i]);
    	}
    }A;
    
    inline int read()
    {
    	int now=0,f=1; char c=gc();
    	for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
    	for(;isdigit(c);now=now*10+c-48,c=gc());
    	return now*f;
    }
    bool cmpl(const Node &a,const Node &b)
    {
    	return a.l<b.l;
    }
    bool cmpr(const Node &a,const Node &b)
    {
    	return a.r>b.r;
    }
    
    int main()
    {
    	int n=read(),Q=read();
    	for(int i=1; i<=n; ++i)
    	{
    		LL x=read(),y=read();
    		A.A[i]=2*y-x, A.B[i]=2*y+x;
    	}
    	A.Discrete(n);
    //ST
    	int cnt=A.cnt;
    	for(int i=1; i<=n; ++i)
    	{
    		node[i]=(Node){A.A[i],A.B[i],i};
    		ST.Insert(1,cnt,1,A.A[i],i), ST.Insert(1,cnt,1,A.B[i],i);
    	}
    	ST.Maintain(1,cnt,1);
    //IT
    	Vec a,b; int root=0;
    	for(int i=1; i<=n; ++i) a.pb(node[i]),b.pb(node[i]);
    	std::sort(a.begin(),a.end(),cmpl), std::sort(b.begin(),b.end(),cmpr);
    	IT.Build(root,a,b);
    //Query
    	for(int p=0; Q--; )
    	{
    		LL x=-1-((p+read())%mod),y=(p+read())%mod;
    		int L=A.Find(2*y+x),R=A.Find2(2*y-x);
    		std::vector<int>().swap(Ans), std::vector<int>().swap(Ans2);
    //
    		if(L<=R)
    		{
    			ST.Query(1,cnt,1,L,R), IT.Query(root,L);
    //			if(De) {puts("ST Query:"); for(auto a:Ans) printf("%d ",a); De&&pc('
    ');}
    			std::vector<int> tmp;
    			for(auto i:Ans2) if(node[i].l<=L && node[i].r>=R) tmp.pb(i);
    //			if(De) {puts("IT Query:"); for(auto a:tmp) printf("%d ",a); De&&pc('
    ');}
    			Merge(Ans,Ans,tmp);
    		}
    //
    		LL res=0,t=1; int las=-1;
    		for(auto a:Ans)
    			if(a!=las) res+=a*t%mod, t=t*5782344%mod, las=a;
    		printf("%d
    ",p=(int)(res%mod));//(int)(res%mod)!=(int)res%mod!
    	}
    
    	return 0;
    }
    

    线段树套线段树:

    /*
    TLE on #2
    */
    #include <bits/stdc++.h>
    #define pc putchar
    #define gc() getchar()
    #define mod 1000000007
    typedef long long LL;
    const int N=1e5+5;
    //const LL M1=2e9,M2=3000000000ll,M3=1e9;
    
    std::vector<int> Ans;
    struct Segment_Tree_2D
    {
    	#define S N*170
    	#define ls son[x][0]
    	#define rs son[x][1]
    	#define lson ls,l,m
    	#define rson rs,m+1,r
    	int tot,cntB,son[S][2],p,id,L,R;
    	std::vector<int> vec[S];
    	#undef S
    	void Ins(int &x,int _p,int _id)
    	{
    		p=_p, id=_id, Insert(x,1,cntB);
    	}
    	void Insert(int &x,int l,int r)
    	{
    		if(!x) x=++tot; vec[x].emplace_back(id);
    		if(l==r) return;
    		int m=l+r>>1; p<=m?Insert(lson):Insert(rson);
    	}
    	void Qry(int x,int _L,int _R)
    	{
    		L=_L, R=_R, Query(x,1,cntB);
    	}
    	void Query(int x,int l,int r)
    	{
    		if(!x) return;
    		if(L<=l && r<=R)
    		{
    			for(auto a:vec[x]) Ans.emplace_back(a);
    			return;
    		}
    		int m=l+r>>1;
    		if(L<=m) Query(lson);
    		if(m<R) Query(rson);
    	}
    	#undef ls
    	#undef rs
    	#undef lson
    	#undef rson
    };
    struct Segment_Tree_1D
    {
    	#define S N
    	#define ls son[x][0]
    	#define rs son[x][1]
    	#define lson ls,l,m
    	#define rson rs,m+1,r
    	int tot,cntA,son[S][2],root[S],id,p1,p2,L1,R1,L2,R2;
    	Segment_Tree_2D T;
    	#undef S
    	void Ins(int &x,int _p1,int _p2,int _id)
    	{
    		p1=_p1, p2=_p2, id=_id, Insert(x,1,cntA);
    	}
    	void Insert(int &x,int l,int r)
    	{
    		if(!x) x=++tot; T.Ins(root[x],p2,id);
    		if(l==r) return;
    		int m=l+r>>1; p1<=m?Insert(lson):Insert(rson);
    	}
    	void Qry(int x,int _L1,int _R1,int _L2,int _R2)
    	{
    		if(_L1<=_R1 && _L2<=_R2)
    			L1=_L1, R1=_R1, L2=_L2, R2=_R2, Query(x,1,cntA);
    	}
    	void Query(int x,int l,int r)
    	{
    		if(!x) return;
    //		printf("Query(%d %lld~%lld %lld~%lld %lld~%lld)
    ",x,l,r,L1,R1,L2,R2);
    		if(L1<=l && r<=R1)
    		{
    			T.Qry(root[x],L2,R2);
    			return;
    		}
    		int m=l+r>>1;
    		if(L1<=m) Query(lson);
    		if(m<R1) Query(rson);
    	}
    }T;
    struct Array
    {
    	int cnt,val[N];
    	LL A[N],Ref[N];
    	int Find(LL v)
    	{
    		if(Ref[cnt]<v) return cnt+1;
    		int l=1,r=cnt,mid;
    		while(l<r)
    			if(Ref[mid=l+r>>1]<v) l=mid+1;
    			else r=mid;
    		return l;
    	}
    	int Find2(LL v)
    	{
    		if(Ref[1]>v) return 0;
    		int l=1,r=cnt,mid,ans=0;
    		while(l<=r)
    			if(Ref[mid=l+r>>1]<=v) l=mid+1,ans=mid;
    			else r=mid-1;
    		return ans;
    	}
    	void Discrete(const int n)
    	{
    		for(int i=1; i<=n; ++i) Ref[i]=A[i];
    		std::sort(Ref+1,Ref+1+n);
    		cnt=1;
    		for(int i=2; i<=n; ++i) if(Ref[i]!=Ref[i-1]) Ref[++cnt]=Ref[i];
    		for(int i=1; i<=n; ++i) val[i]=Find(A[i]);
    	}
    }A,B;
    
    inline int read()
    {
    	int now=0,f=1; char c=gc();
    	for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
    	for(;isdigit(c);now=now*10+c-48,c=gc());
    	return now*f;
    }
    #define De 0
    int main()
    {
    	int n=read(),Q=read();
    	int root=0;
    	for(int i=1; i<=n; ++i)
    	{
    		LL x=read(),y=read();
    		A.A[i]=x+2*y, B.A[i]=2*y-x;
    	}
    	A.Discrete(n), B.Discrete(n);
    	int cntA=A.cnt,cntB=B.cnt;
    	T.cntA=A.cnt, T.T.cntB=B.cnt;
    	for(int i=1; i<=n; ++i) T.Ins(root,A.val[i],B.val[i],i);
    	for(int p=0; Q--; )
    	{
    		LL x=-1-((p+read())%mod),y=(p+read())%mod;
    //		De&&printf("(%d,%d)
    ",x,y);
    		int L1=A.Find(2*y+x),R1=cntA,L2=1,R2=B.Find2(2*y-x);
    //		De&&printf("%d~%d %d~%d  %d %d
    ",L1,R1,L2,R2,2*y+x,2*y-x);
    		Ans.clear(), T.Qry(root,L1,R1,L2,R2);
    		LL res=0,t=1;
    		std::sort(Ans.begin(),Ans.end());
    		if(De) for(auto a:Ans) printf("%d ",a); De&&pc('
    ');
    		for(auto a:Ans) res+=a*t%mod, t=t*5782344%mod;
    		p=(int)(res%mod);
    		printf("%d
    ",p);
    	}
    
    	return 0;
    }
    
    ------------------------------------------------------------------------------------------------------------------------
    无心插柳柳成荫才是美丽
    有哪种美好会来自于刻意
    这一生波澜壮阔或是不惊都没问题
    只愿你能够拥抱那种美丽
    ------------------------------------------------------------------------------------------------------------------------
  • 相关阅读:
    Maven 学习笔记——Maven和Eclipse(2)
    Maven 学习笔记——Maven环境配置(1)
    Selenium WebDriver VS Selenium RC
    ASP.NET_SessionId
    'NuGet.VisualStudio.Interop 报错
    HTTP Error 403.14 Forbidden
    关于Python字符编码encode和decode
    zabbix安装步骤
    centos7 上搭建私有云
    Python读写改Excel的方法
  • 原文地址:https://www.cnblogs.com/SovietPower/p/14399545.html
Copyright © 2011-2022 走看看