您的位置:首页 > 其它

[bzoj 3236--AHOI2013]作业

2018-03-04 16:06 197 查看


这道题跟Gty的二逼妹子序列灰常像,就是“作业”的第二个问。但这道题最大的不同,就是不卡时间,用树状数组可以过(不过就是比较慢),分块就快一(hen)点(duo)。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
struct node
{
int l,r,id,s1,s2,sl,sr;
}q[1000010];
int n,m;
int a[100010],belong[100010],bl[100010],br[100010],num[100010],t[100010],tt[100010];
void fk()
{
int cnt=sqrt(n);
for(int i=1;i<=n;i++)
{
int bg=(i-1)/cnt+1;
belong[i]=bg;
if(bl[bg]==0)bl[bg]=i,br[bg-1]=i-1;
}
br[belong
]=n;
}
bool cmp1(node a,node b)
{
if(belong[a.l]==belong[b.l])
{
if(a.r>b.r)return false;
if(a.r<b.r)return true;
return 0;
}
if(belong[a.l]>belong[b.l])return false;
if(belong[a.l]<belong[b.l])return true;
return 0;
}
bool cmp2(node a,node b)
{
if(a.id>b.id)return false;
if(a.id<b.id)return true;
return 0;
}
void del(int x)
{
num[x]--;
if(num[x]==0)t[belong[x]]--;
tt[belong[x]]--;
}
void add(int x)
{
num[x]++;
if(num[x]==1)t[belong[x]]++;
tt[belong[x]]++;
}
int sum,ans;
void sle(int x,int y)
{
sum=ans=0;
int bx=belong[x],by=belong[y];
if(bx==by)
{
for(int i=x;i<=y;i++)
{
if(num[i]>0)sum++;
ans+=num[i];
}
}
else
{
for(int i=bx+1;i<=by-1;i++)sum+=t[i],ans+=tt[i];
for(int i=x;i<=br[bx];i++)
{
if(num[i]>0)sum++;
ans+=num[i];
}
for(int i=bl[by];i<=y;i++)
{
if(num[i]>0)sum++;
ans+=num[i];
}
}
}
void solve()
{
int l=1,r=0;
for(int i=1;i<=m;i++)
{
for(int j=q[i].r+1;j<=r;j++)del(a[j]);
for(int j=r+1;j<=q[i].r;j++)add(a[j]);
for(int j=l;j<=q[i].l-1;j++)del(a[j]);
for(int j=q[i].l;j<=l-1;j++)add(a[j]);
l=q[i].l,r=q[i].r;
sle(q[i].sl,q[i].sr);
q[i].s1=ans;q[i].s2=sum;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].sl,&q[i].sr);q[i].id=i;
}
fk();
sort(q+1,q+m+1,cmp1);
solve();
sort(q+1,q+m+1,cmp2);
for(int i=1;i<=m;i++)printf("%d %d\n",q[i].s1,q[i].s2);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  bzoj 莫队 分块 AHOI