P4396 [AHOI2013]作业
题目描述
solution
莫队+树状数组的裸题(莫队+分块,CDQ分治都可以,莫队+线段树大概需要卡常)。
时间复杂度
Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+50;
inline int read()
{
int f=1,x=0; char c=getchar();
while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }
while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }
return x*f;
}
int n,m,Size,Ans1[MAXN],Ans2[MAXN],a[MAXN],cnt[MAXN];
struct pnode{int l,r,a,b,id,x; } p[MAXN];
struct Tree_Array
{
int tree[MAXN<<1];
int lowbit(int x){ return x&(-x); }
void change(int x,int y) { for (;x<=n;x+=lowbit(x)) tree[x]+=y; }
int query(int x){ int ans=0; for (;x;x-=lowbit(x)) ans+=tree[x]; return ans; }
} tree1,tree2;
int compare(pnode x,pnode y){ return (x.x<y.x)||(x.x==y.x&&x.r<y.r); }
int main()
{
n=read(),m=read(),Size=trunc(sqrt(n));
for (int i=1;i<=n;i++) a[i]=read();
for (int i=1;i<=m;i++)
{
p[i].l=read(),p[i].r=read(),p[i].a=read(),p[i].b=read();
p[i].id=i,p[i].x=(p[i].l-1)/Size+1;
}
sort(p+1,p+m+1,compare);
int L=1,R=0;
for (int i=1;i<=m;i++)
{
while (L<p[i].l) cnt[a[L]]--,tree1.change(a[L],-1),tree2.change(a[L],cnt[a[L]]==0?-1:0),L++;
while (L>p[i].l) L--,cnt[a[L]]++,tree1.change(a[L], 1),tree2.change(a[L],cnt[a[L]]==1? 1:0);
while (R<p[i].r) R++,cnt[a[R]]++,tree1.change(a[R], 1),tree2.change(a[R],cnt[a[R]]==1? 1:0);
while (R>p[i].r) cnt[a[R]]--,tree1.change(a[R],-1),tree2.change(a[R],cnt[a[R]]==0?-1:0),R--;
Ans1[p[i].id]=tree1.query(p[i].b)-tree1.query(p[i].a-1);
Ans2[p[i].id]=tree2.query(p[i].b)-tree2.query(p[i].a-1);
}
for (int i=1;i<=m;i++) printf("%d %d\n",Ans1[i],Ans2[i]);
return 0;
}

本文详细解析了AHOI2013竞赛中的作业问题,采用莫队算法结合树状数组进行求解,阐述了算法原理及其实现细节,包括时间复杂度分析和完整代码示例。

被折叠的 条评论
为什么被折叠?



