您的位置:首页 > 其它

BZOJ 3809 Gty的二逼妹子序列

2017-02-23 17:03 120 查看
暴力。。。严格的说是mlogn+m√nlogn的。。。就是莫队+BIT。

然后我们可以按照值域分块,这样修改O(1)查询O(√n),这样总复杂度就是2*m*√n。

有点像做了一个时间复杂度的权衡。。。看起来查询变慢了,事实上总复杂度是变快了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100050
#define maxm 1000050
using namespace std;
int n,m,len=300,blo[maxn],st[maxn],ret=0,val[maxn],cnt[maxn],a[maxn],ans[maxm],p1,p2;
int a1,a2,a3,a4;
struct query
{
int l,r,a,b,id;
query (int l,int r,int a,int b,int id):l(l),r(r),a(a),b(b),id(id) {}
query () {}
}q[maxm];
int read()
{
char ch;int data=0;
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9')
{
data=data*10+ch-'0';
ch=getchar();
}
return data;
}
bool cmp(query x,query y)
{
if (blo[x.l]==blo[y.l]) return x.r<y.r;
return blo[x.l]<blo[y.l];
}
void build()
{
ret=1;
for (int i=1;i<=n;i++)
{
blo[i]=ret;
if (!(i%len)) {st[ret]=i;if (i!=n) ret++;}
}
if (n%len) st[ret]=n;
}
void modify(int x,int y)
{
bool flag=cnt[x];
cnt[x]+=y;
if ((!cnt[x]) && (flag)) val[blo[x]]--;
if ((cnt[x]) && (!flag)) val[blo[x]]++;
}
int ask(int l,int r)
{
int ret1=0,ret2=0;
for (int i=1;i<=blo[l-1]-1;i++) ret1+=val[i];
for (int i=st[blo[l-1]-1]+1;i<=l-1;i++) ret1+=(cnt[i]>0);
for (int i=1;i<=blo[r]-1;i++) ret2+=val[i];
for (int i=st[blo[r]-1]+1;i<=r;i++) ret2+=(cnt[i]>0);
return ret2-ret1;
}
int main()
{
n=read();m=read();
for (int i=1;i<=n;i++) a[i]=read();
for (int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&a1,&a2,&a3,&a4);
q[i]=query(a1,a2,a3,a4,i);
}
build();
sort(q+1,q+m+1,cmp);
for (int i=1;i<=m;i++)
{
for (;p1>q[i].l;p1--) modify(a[p1-1],1);
for (;p1<q[i].l;p1++) modify(a[p1],-1);
for (;p2>q[i].r;p2--) modify(a[p2],-1);
for (;p2<q[i].r;p2++) modify(a[p2+1],1);
ans[q[i].id]=ask(q[i].a,q[i].b);
}
for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: