您的位置:首页 > 其它

【bzoj3809】Gty的二逼妹子序列 莫队+分块

2016-11-29 13:47 351 查看
AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=3809

【题解】

如果没有区间[a,b]的限制,那么这题就是一道模板题。

查询答案的时候我们需要得到区间[a,b]的答案,很容易想到树状数组。

但是树状数组的时间复杂度是O(n*logn*√n),不足以卡过此题。

所以我们就用到了分块大法,时间复杂度O(n*√n)/*************
bzoj 3809
by chty
2016.11.29
*************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<algorithm>
using namespace std;
#define FILE "read"
#define MAXN 100010
#define MAXM 1000010
#define up(i,j,n) for(int i=j;i<=n;i++)
#define down(i,j,n) for(int i=j;i>=n;i--)
namespace INIT{
char buf[1<<15],*fs,*ft;
inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
inline int read(){
int x=0,f=1; char ch=getc();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getc();}
while(isdigit(ch)) {x=x*10+ch-'0'; ch=getc();}
return x*f;
}
}using namespace INIT;
struct node{int x,y,a,b,id;}q[MAXM];
int n,m,block,a[MAXN],ans[MAXM],cnt[MAXN],vis[MAXN],blo[MAXN];
bool cmp(node a,node b) {return a.x/block==b.x/block?a.y<b.y:a.x/block<b.x/block;}
void add(int x){
vis[x]^=1;
blo[x/block]+=vis[x]?1:-1;
}
void updata(int x,int v){
if(!cnt[x]) add(x);
cnt[x]+=v;
if(!cnt[x]) add(x);
}
int query(int x,int y){
int l=x/block,r=y/block,sum(0);
if(l==r){
up(i,x,y) sum+=vis[i];
return sum;
}
up(i,l+1,r-1) sum+=blo[i];
up(i,x,(l+1)*block-1) sum+=vis[i];
up(i,r*block,y) sum+=vis[i];
return sum;
}
void solve(){
sort(q+1,q+m+1,cmp);
int l(1),r(0);
up(i,1,m){
while(q[i].y>r) updata(a[++r],1);
while(q[i].y<r) updata(a[r--],-1);
while(q[i].x<l) updata(a[--l],1);
while(q[i].x>l) updata(a[l++],-1);
ans[q[i].id]=query(q[i].a,q[i].b);
}
up(i,1,m) printf("%d\n",ans[i]);
}
void init(){
n=read(); m=read(); block=(int)sqrt(n*1.0);
up(i,1,n) a[i]=read();
up(i,1,m) q[i].x=read(),q[i].y=read(),q[i].a=read(),q[i].b=read(),q[i].id=i;
}
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
init();
solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: