博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

BZOJ.3809.Gty的二逼妹子序列(分块 莫队)

题目链接

/*
25832 kb  26964 ms
莫队+树状数组:增加/删除/查询 都是O(logn)的,总时间复杂度O(m*sqrt(n)*logn),卡不过 
莫队+分块:这样查询虽然变成了sqrt(n),但是修改是O(1)的 
考虑对权值进行分块 
细节... 
*/
#include<cmath>
#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
const int N=1e5+5,M=1e6+5;

int n,m,A[N],size,Ans[M],belong[N],times[N],bloans[N];
struct Ques
{
	int l,r,a,b,id;
	bool operator <(const Ques &x)const
	{
		return belong[l]==belong[x.l] ? r<x.r : l<x.l;
	}
}q[M];

inline int read()
{
	int now=0,f=1;register char c=getchar();
	for(;!isdigit(c);c=getchar())
	  if(c=='-') f=-1;
	for(;isdigit(c);now=now*10+c-'0',c=getchar());
	return now*f;
}

int Query(int l,int r)
{
	int res=0,t=min(r,belong[l]*size);
	for(int i=l;i<=t;++i)
		if(times[i]) ++res;
	if(belong[l]!=belong[r])
		for(int i=(belong[r]-1)*size+1;i<=r;++i)
			if(times[i]) ++res;
	for(int i=belong[l]+1;i<belong[r];++i)
		res+=bloans[i];
	return res;
}
inline void Add(int p)
{
	if(!times[p]) ++bloans[belong[p]];
	++times[p];
}
inline void Subd(int p)
{
	--times[p];
	if(!times[p]) --bloans[belong[p]];
}

int main()
{
	n=read(),m=read();size=sqrt(n);
	for(int i=1;i<=n;++i)
		A[i]=read(), belong[i]=(i-1)/size+1;
	for(int i=1;i<=m;++i)
		q[i].l=read(), q[i].r=read(), q[i].a=read(), q[i].b=read(), q[i].id=i;
	sort(q+1,q+1+m);
	for(int i=1,l=1,r=0;i<=m;++i)
	{
		while(l<q[i].l) Subd(A[l++]);
		while(l>q[i].l) Add(A[--l]);
		while(r<q[i].r) Add(A[++r]);
		while(r>q[i].r) Subd(A[r--]);
		Ans[q[i].id]=Query(q[i].a,q[i].b);
	}
	for(int i=1;i<=m;++i)
		printf("%d\n",Ans[i]);

	return 0;
}

2019.11.14:

//2.04s	25.05MB 没以前跑得快...自闭了 
#include <cmath>
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
//#define MAXIN 500000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=1e5+5,M=1e6+5;

int size,bel[N],val[N],bloans[N],times[N],Ans[M];
//char IN[MAXIN],*SS=IN,*TT=IN;
struct Queries
{
	int l,r,a,b,id;
	bool operator <(const Queries &x)const
	{
		return bel[l]==bel[x.l]?r<x.r:l<x.l;
	}
}q[M];

inline int read()
{
	int now=0;register char c=gc();
	for(;!isdigit(c);c=gc());
	for(;isdigit(c);now=now*10+c-48,c=gc());
	return now;
}
inline void Add(int x)
{
	!times[x]&&(++bloans[bel[x]]), ++times[x];
}
inline void Subd(int x)
{
	--times[x], !times[x]&&(--bloans[bel[x]]);
}
inline int Query(int l,int r)
{
	int res=0;
	for(int i=bel[l]+1; i<bel[r]; ++i) res+=bloans[i];
	for(int i=l,t=std::min(bel[l]*size,r); i<=t; ++i) res+=(times[i]!=0);
	if(bel[l]!=bel[r]) for(int i=(bel[r]-1)*size+1; i<=r; ++i) res+=(times[i]!=0);
	return res;
}

int main()
{
	const int n=read(),m=read(),size=sqrt(n); ::size=size;
	for(int i=1; i<=n; ++i) val[i]=read(), bel[i]=(i-1)/size+1;
	for(int i=1; i<=m; ++i) q[i]=(Queries){read(),read(),read(),read(),i};
	std::sort(q+1,q+1+m);
	for(int i=1,l=1,r=0; i<=m; ++i)
	{
		int ln=q[i].l,rn=q[i].r;
		while(l>ln) Add(val[--l]);
		while(r<rn) Add(val[++r]);
		while(l<ln) Subd(val[l++]);
		while(r>rn) Subd(val[r--]);
		Ans[q[i].id]=Query(q[i].a,q[i].b);
	}
	for(int i=1; i<=m; printf("%d\n",Ans[i++]));

	return 0;
}
posted @ 2018-02-09 13:23  SovietPower  阅读(162)  评论(0编辑  收藏  举报