把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P4867 Gty的二逼妹子序列

题面传送门
空间这么小,只能莫队。在移动时用域值分块\(O(1)\)修改即可。
代码实现:

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int n,m,k,x,y,z,ans[1000039],a[100039],l,r,mid,f[100039],ku[100039],st[100039];
struct yyy{int x,y,a,b,num;}fs[1000039],tmp;
inline bool cmp(yyy x,yyy y){return (x.x/k==y.x/k)?(((x.x/k)&1)?x.y<y.y:x.y>y.y):x.x<y.x;}
inline void read(int &x){
	char s=getchar();x=0;
	while(s<'0'||s>'9') s=getchar();
	while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+(s^48),s=getchar();
}
inline void print(int x){
	if(x>9) print(x/10);
	putchar(x%10+48);
}
int main(){
	register int i,j,l=1,r=0;
	register yyy tmp;
	read(n);read(m);
	k=sqrt(n);
	for(i=1;i<=n;i++) read(a[i]);
	for(i=1;i<=m;i++) read(fs[i].x),read(fs[i].y),read(fs[i].a),read(fs[i].b),fs[i].num=i;
	sort(fs+1,fs+m+1,cmp);
	l=1;
	for(i=1;i<=m;i++){
		tmp=fs[i];
		while(l>tmp.x){
			l--;
			f[a[l]]++;
			if(f[a[l]]==1) st[a[l]]=1,ku[a[l]/k]++;
		}
		while(r<tmp.y){
			r++;
			f[a[r]]++;
			if(f[a[r]]==1) st[a[r]]=1,ku[a[r]/k]++;
		}
		while(l<tmp.x){
			if(f[a[l]]==1) st[a[l]]=0,ku[a[l]/k]--;
			f[a[l]]--;
			l++;
		}
		while(r>tmp.y){
			if(f[a[r]]==1) st[a[r]]=0,ku[a[r]/k]--;
			f[a[r]]--;
			r--;
		}
		if(tmp.a/k==tmp.b/k) for(j=tmp.a;j<=tmp.b;j++) ans[tmp.num]+=st[j];
		else {
			for(j=tmp.a;j<tmp.a/k*k+k;j++) ans[tmp.num]+=st[j];
			for(j=tmp.a/k+1;j<tmp.b/k;j++) ans[tmp.num]+=ku[j];
			for(j=tmp.b/k*k;j<=tmp.b;j++) ans[tmp.num]+=st[j];
		}
	}
	for(i=1;i<=m;i++) print(ans[i]),putchar('\n');
}
posted @ 2020-07-12 22:20  275307894a  阅读(30)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end