BZOJ 3809 Gty的二逼妹子序列 莫隊算法+分塊


題目大意:給定一個序列,多次詢問[l,r]區間內[a,b]范圍內的數有多少

內存28MB,樹套樹可以歇菜了

首先普通的莫隊+樹狀數組應該都能想到 這樣做每次增加/刪除一個點是O(logn)的 查詢也是O(logn) 時間復雜度O(m√nlogn) 過(bu)不(hao)去(ka)

考慮將樹狀數組 改成分塊 這樣雖然查詢變成了O(√n) 但是修改變成了O(1)的

這樣就把時間復雜度降到了O(m√n) 常數寫小點親測能卡過去

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std;
struct query{
int l,r,a,b,_id;
bool operator < (const query &x) const;
}queries[1001001];
int n,m,block,l=1,r=0;
int a[M],belong[M],ans[1001001];
int cnt[M],block_cnt[330];
bool query :: operator < (const query &x) const
{
if( belong[l] != belong[x.l] )
return l < x.l;
return r < x.r;
}
namespace IStream{
const int L=1<<15;
char buffer[L],*S,*T;
inline char Get_Char()
{
if(S==T)
{
T=(S=buffer)+fread(buffer,1,L,stdin);
if(S==T) return EOF;
}
return *S++;
}
inline int Get_Int()
{
char c;
int re=0;
for(c=Get_Char();c<'0'||c>'9';c=Get_Char());
while(c>='0'&&c<='9')
re=(re<<1)+(re<<3)+(c-'0'),c=Get_Char();
return re;
}
}
class OStream{
private:
static const int L=1<<15;
char stack[20];int top;
char buffer[L],*S;
public:
OStream()
{
S=buffer;
}
void Put_Int(int x)
{
stack[++top]='\n';
if(!x) stack[++top]='0';
else while(x)
stack[++top]=x%10+'0',x/=10;
while(top)
{
if(S==buffer+L-1)
{
printf("%s",buffer);
S=buffer;
}
*S++=stack[top--];
}
}
~OStream()
{
*S=0;
puts(buffer);
}
}os;
inline void Update(int x)
{
cnt[x]++;
if(cnt[x]==1)
block_cnt[belong[x]]++;
}
inline void Downdate(int x)
{
cnt[x]--;
if(cnt[x]==0)
block_cnt[belong[x]]--;
}
int Query(int x,int y)
{
int i,re=0;
if(belong[y]-belong[x]<=1)
{
for(i=x;i<=y;i++)
re+=(bool)cnt[i];
return re;
}
for(i=belong[x]+1;i<belong[y];i++)
re+=block_cnt[i];
for(i=x;i<=belong[x]*block;i++)
re+=(bool)cnt[i];
for(i=y;i>=(belong[y]-1)*block+1;i--)
re+=(bool)cnt[i];
return re;
}
int main()
{
int i;
cin>>n>>m;
if(n<=10)
block=(int)sqrt(n);
else
block=(int)sqrt(n);
for(i=1;i<=n;i++)
{
a[i]=IStream::Get_Int();
belong[i]=(i-1)/block+1;
}
for(i=1;i<=m;i++)
{
queries[i].l=IStream::Get_Int();
queries[i].r=IStream::Get_Int();
queries[i].a=IStream::Get_Int();
queries[i].b=IStream::Get_Int();
queries[i]._id=i;
}
sort(queries+1,queries+m+1);
for(i=1;i<=m;i++)
{
while(r<queries[i].r)
Update(a[++r]);
while(l>queries[i].l)
Update(a[--l]);
while(r>queries[i].r)
Downdate(a[r--]);
while(l<queries[i].l)
Downdate(a[l++]);
ans[queries[i]._id]=Query(queries[i].a,queries[i].b);
}
for(i=1;i<=m;i++)
os.Put_Int(ans[i]);
return 0;
}



注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com